Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
97a0df77
authored
Sep 09, 2020
by
kimvde
Committed by
Oliver Woodman
Oct 17, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Support android.resource URI scheme
Issue: #7866 PiperOrigin-RevId: 330736774
parent
8955cd3a
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
79 additions
and
29 deletions
RELEASENOTES.md
library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java
RELEASENOTES.md
View file @
97a0df77
# Release notes
### 2.12.1 ###
*
Data sources:
*
Add support for
`android.resource`
URI scheme in
`RawResourceDataSource`
(
[
#7866
](
https://github.com/google/ExoPlayer/issues/7866
)
).
### 2.12.0 (2020-09-11) ###
To learn more about what's new in 2.12, read the corresponding
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java
View file @
97a0df77
...
...
@@ -15,6 +15,7 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
upstream
;
import
android.content.ContentResolver
;
import
android.content.Context
;
import
android.net.Uri
;
import
androidx.annotation.Nullable
;
...
...
@@ -39,6 +40,9 @@ import java.util.Map;
* <li>rawresource: For fetching data from a raw resource in the application's apk (e.g.
* rawresource:///resourceId, where rawResourceId is the integer identifier of the raw
* resource).
* <li>android.resource: For fetching data in the application's apk (e.g.
* android.resource:///resourceId or android.resource://resourceType/resourceName). See {@link
* RawResourceDataSource} for more information about the URI form.
* <li>content: For fetching data from a content URI (e.g. content://authority/path/123).
* <li>rtmp: For fetching data over RTMP. Only supported if the project using ExoPlayer has an
* explicit dependency on ExoPlayer's RTMP extension.
...
...
@@ -58,7 +62,9 @@ public final class DefaultDataSource implements DataSource {
private
static
final
String
SCHEME_CONTENT
=
"content"
;
private
static
final
String
SCHEME_RTMP
=
"rtmp"
;
private
static
final
String
SCHEME_UDP
=
"udp"
;
private
static
final
String
SCHEME_DATA
=
DataSchemeDataSource
.
SCHEME_DATA
;
private
static
final
String
SCHEME_RAW
=
RawResourceDataSource
.
RAW_RESOURCE_SCHEME
;
private
static
final
String
SCHEME_ANDROID_RESOURCE
=
ContentResolver
.
SCHEME_ANDROID_RESOURCE
;
private
final
Context
context
;
private
final
List
<
TransferListener
>
transferListeners
;
...
...
@@ -182,9 +188,9 @@ public final class DefaultDataSource implements DataSource {
dataSource
=
getRtmpDataSource
();
}
else
if
(
SCHEME_UDP
.
equals
(
scheme
))
{
dataSource
=
getUdpDataSource
();
}
else
if
(
DataSchemeDataSource
.
SCHEME_DATA
.
equals
(
scheme
))
{
}
else
if
(
SCHEME_DATA
.
equals
(
scheme
))
{
dataSource
=
getDataSchemeDataSource
();
}
else
if
(
SCHEME_RAW
.
equals
(
scheme
))
{
}
else
if
(
SCHEME_RAW
.
equals
(
scheme
)
||
SCHEME_ANDROID_RESOURCE
.
equals
(
scheme
)
)
{
dataSource
=
getRawResourceDataSource
();
}
else
{
dataSource
=
baseDataSource
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java
View file @
97a0df77
...
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.upstream;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
castNonNull
;
import
static
java
.
lang
.
Math
.
min
;
import
android.content.ContentResolver
;
import
android.content.Context
;
import
android.content.res.AssetFileDescriptor
;
import
android.content.res.Resources
;
...
...
@@ -34,9 +35,20 @@ import java.io.InputStream;
/**
* A {@link DataSource} for reading a raw resource inside the APK.
*
* <p>URIs supported by this source are of the form {@code rawresource:///rawResourceId}, where
* rawResourceId is the integer identifier of a raw resource. {@link #buildRawResourceUri(int)} can
* be used to build {@link Uri}s in this format.
* <p>URIs supported by this source are of one of the forms:
*
* <ul>
* <li>{@code rawresource:///id}, where {@code id} is the integer identifier of a raw resource.
* <li>{@code android.resource:///id}, where {@code id} is the integer identifier of a raw
* resource.
* <li>{@code android.resource://[package]/[type/]name}, where {@code package} is the name of the
* package in which the resource is located, {@code type} is the resource type and {@code
* name} is the resource name. The package and the type are optional. Their default value is
* the package of this application and "raw", respectively. Using the two other forms is more
* efficient.
* </ul>
*
* <p>{@link #buildRawResourceUri(int)} can be used to build supported {@link Uri}s.
*/
public
final
class
RawResourceDataSource
extends
BaseDataSource
{
...
...
@@ -67,6 +79,7 @@ public final class RawResourceDataSource extends BaseDataSource {
public
static
final
String
RAW_RESOURCE_SCHEME
=
"rawresource"
;
private
final
Resources
resources
;
private
final
String
packageName
;
@Nullable
private
Uri
uri
;
@Nullable
private
AssetFileDescriptor
assetFileDescriptor
;
...
...
@@ -80,33 +93,55 @@ public final class RawResourceDataSource extends BaseDataSource {
public
RawResourceDataSource
(
Context
context
)
{
super
(
/* isNetwork= */
false
);
this
.
resources
=
context
.
getResources
();
this
.
packageName
=
context
.
getPackageName
();
}
@Override
public
long
open
(
DataSpec
dataSpec
)
throws
RawResourceDataSourceException
{
try
{
Uri
uri
=
dataSpec
.
uri
;
this
.
uri
=
uri
;
if
(!
TextUtils
.
equals
(
RAW_RESOURCE_SCHEME
,
uri
.
getScheme
()))
{
throw
new
RawResourceDataSourceException
(
"URI must use scheme "
+
RAW_RESOURCE_SCHEME
);
}
int
resourceId
;
Uri
uri
=
dataSpec
.
uri
;
this
.
uri
=
uri
;
int
resourceId
;
if
(
TextUtils
.
equals
(
RAW_RESOURCE_SCHEME
,
uri
.
getScheme
())
||
(
TextUtils
.
equals
(
ContentResolver
.
SCHEME_ANDROID_RESOURCE
,
uri
.
getScheme
())
&&
uri
.
getPathSegments
().
size
()
==
1
&&
Assertions
.
checkNotNull
(
uri
.
getLastPathSegment
()).
matches
(
"\\d+"
)))
{
try
{
resourceId
=
Integer
.
parseInt
(
Assertions
.
checkNotNull
(
uri
.
getLastPathSegment
()));
}
catch
(
NumberFormatException
e
)
{
throw
new
RawResourceDataSourceException
(
"Resource identifier must be an integer."
);
}
transferInitializing
(
dataSpec
);
AssetFileDescriptor
assetFileDescriptor
=
resources
.
openRawResourceFd
(
resourceId
);
this
.
assetFileDescriptor
=
assetFileDescriptor
;
if
(
assetFileDescriptor
==
null
)
{
throw
new
RawResourceDataSourceException
(
"Resource is compressed: "
+
uri
);
}
else
if
(
TextUtils
.
equals
(
ContentResolver
.
SCHEME_ANDROID_RESOURCE
,
uri
.
getScheme
()))
{
String
path
=
Assertions
.
checkNotNull
(
uri
.
getPath
());
if
(
path
.
startsWith
(
"/"
))
{
path
=
path
.
substring
(
1
);
}
@Nullable
String
host
=
uri
.
getHost
();
String
resourceName
=
(
TextUtils
.
isEmpty
(
host
)
?
""
:
(
host
+
":"
))
+
path
;
resourceId
=
resources
.
getIdentifier
(
resourceName
,
/* defType= */
"raw"
,
/* defPackage= */
packageName
);
if
(
resourceId
==
0
)
{
throw
new
RawResourceDataSourceException
(
"Resource not found."
);
}
FileInputStream
inputStream
=
new
FileInputStream
(
assetFileDescriptor
.
getFileDescriptor
());
this
.
inputStream
=
inputStream
;
}
else
{
throw
new
RawResourceDataSourceException
(
"URI must either use scheme "
+
RAW_RESOURCE_SCHEME
+
" or "
+
ContentResolver
.
SCHEME_ANDROID_RESOURCE
);
}
transferInitializing
(
dataSpec
);
AssetFileDescriptor
assetFileDescriptor
=
resources
.
openRawResourceFd
(
resourceId
);
this
.
assetFileDescriptor
=
assetFileDescriptor
;
if
(
assetFileDescriptor
==
null
)
{
throw
new
RawResourceDataSourceException
(
"Resource is compressed: "
+
uri
);
}
FileInputStream
inputStream
=
new
FileInputStream
(
assetFileDescriptor
.
getFileDescriptor
());
this
.
inputStream
=
inputStream
;
try
{
inputStream
.
skip
(
assetFileDescriptor
.
getStartOffset
());
long
skipped
=
inputStream
.
skip
(
dataSpec
.
position
);
if
(
skipped
<
dataSpec
.
position
)
{
...
...
@@ -114,18 +149,21 @@ public final class RawResourceDataSource extends BaseDataSource {
// skip beyond the end of the data.
throw
new
EOFException
();
}
if
(
dataSpec
.
length
!=
C
.
LENGTH_UNSET
)
{
bytesRemaining
=
dataSpec
.
length
;
}
else
{
long
assetFileDescriptorLength
=
assetFileDescriptor
.
getLength
();
// If the length is UNKNOWN_LENGTH then the asset extends to the end of the file.
bytesRemaining
=
assetFileDescriptorLength
==
AssetFileDescriptor
.
UNKNOWN_LENGTH
?
C
.
LENGTH_UNSET
:
(
assetFileDescriptorLength
-
dataSpec
.
position
);
}
}
catch
(
IOException
e
)
{
throw
new
RawResourceDataSourceException
(
e
);
}
if
(
dataSpec
.
length
!=
C
.
LENGTH_UNSET
)
{
bytesRemaining
=
dataSpec
.
length
;
}
else
{
long
assetFileDescriptorLength
=
assetFileDescriptor
.
getLength
();
// If the length is UNKNOWN_LENGTH then the asset extends to the end of the file.
bytesRemaining
=
assetFileDescriptorLength
==
AssetFileDescriptor
.
UNKNOWN_LENGTH
?
C
.
LENGTH_UNSET
:
(
assetFileDescriptorLength
-
dataSpec
.
position
);
}
opened
=
true
;
transferStarted
(
dataSpec
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment