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
6abe6a67
authored
Sep 09, 2020
by
kimvde
Committed by
kim-vde
Sep 09, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Support android.resource URI scheme
Issue: #7866 PiperOrigin-RevId: 330736774
parent
9e42b24e
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
76 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 @
6abe6a67
...
@@ -4,6 +4,9 @@
...
@@ -4,6 +4,9 @@
*
Track selection:
*
Track selection:
*
Add option to specify multiple preferred audio or text languages.
*
Add option to specify multiple preferred audio or text languages.
*
Data sources:
*
Add support for
`android.resource`
URI scheme in
`RawResourceDataSource`
(
[
#7866
](
https://github.com/google/ExoPlayer/issues/7866
)
).
### 2.12.0 (not yet released - targeted for 2020-09-11) ###
### 2.12.0 (not yet released - targeted for 2020-09-11) ###
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java
View file @
6abe6a67
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
.
upstream
;
package
com
.
google
.
android
.
exoplayer2
.
upstream
;
import
android.content.ContentResolver
;
import
android.content.Context
;
import
android.content.Context
;
import
android.net.Uri
;
import
android.net.Uri
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
...
@@ -39,6 +40,9 @@ import java.util.Map;
...
@@ -39,6 +40,9 @@ import java.util.Map;
* <li>rawresource: For fetching data from a raw resource in the application's apk (e.g.
* <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
* rawresource:///resourceId, where rawResourceId is the integer identifier of the raw
* resource).
* 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>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
* <li>rtmp: For fetching data over RTMP. Only supported if the project using ExoPlayer has an
* explicit dependency on ExoPlayer's RTMP extension.
* explicit dependency on ExoPlayer's RTMP extension.
...
@@ -58,7 +62,9 @@ public final class DefaultDataSource implements DataSource {
...
@@ -58,7 +62,9 @@ public final class DefaultDataSource implements DataSource {
private
static
final
String
SCHEME_CONTENT
=
"content"
;
private
static
final
String
SCHEME_CONTENT
=
"content"
;
private
static
final
String
SCHEME_RTMP
=
"rtmp"
;
private
static
final
String
SCHEME_RTMP
=
"rtmp"
;
private
static
final
String
SCHEME_UDP
=
"udp"
;
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_RAW
=
RawResourceDataSource
.
RAW_RESOURCE_SCHEME
;
private
static
final
String
SCHEME_ANDROID_RESOURCE
=
ContentResolver
.
SCHEME_ANDROID_RESOURCE
;
private
final
Context
context
;
private
final
Context
context
;
private
final
List
<
TransferListener
>
transferListeners
;
private
final
List
<
TransferListener
>
transferListeners
;
...
@@ -182,9 +188,9 @@ public final class DefaultDataSource implements DataSource {
...
@@ -182,9 +188,9 @@ public final class DefaultDataSource implements DataSource {
dataSource
=
getRtmpDataSource
();
dataSource
=
getRtmpDataSource
();
}
else
if
(
SCHEME_UDP
.
equals
(
scheme
))
{
}
else
if
(
SCHEME_UDP
.
equals
(
scheme
))
{
dataSource
=
getUdpDataSource
();
dataSource
=
getUdpDataSource
();
}
else
if
(
DataSchemeDataSource
.
SCHEME_DATA
.
equals
(
scheme
))
{
}
else
if
(
SCHEME_DATA
.
equals
(
scheme
))
{
dataSource
=
getDataSchemeDataSource
();
dataSource
=
getDataSchemeDataSource
();
}
else
if
(
SCHEME_RAW
.
equals
(
scheme
))
{
}
else
if
(
SCHEME_RAW
.
equals
(
scheme
)
||
SCHEME_ANDROID_RESOURCE
.
equals
(
scheme
)
)
{
dataSource
=
getRawResourceDataSource
();
dataSource
=
getRawResourceDataSource
();
}
else
{
}
else
{
dataSource
=
baseDataSource
;
dataSource
=
baseDataSource
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java
View file @
6abe6a67
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.upstream;
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.upstream;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
castNonNull
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
castNonNull
;
import
static
java
.
lang
.
Math
.
min
;
import
static
java
.
lang
.
Math
.
min
;
import
android.content.ContentResolver
;
import
android.content.Context
;
import
android.content.Context
;
import
android.content.res.AssetFileDescriptor
;
import
android.content.res.AssetFileDescriptor
;
import
android.content.res.Resources
;
import
android.content.res.Resources
;
...
@@ -34,9 +35,20 @@ import java.io.InputStream;
...
@@ -34,9 +35,20 @@ import java.io.InputStream;
/**
/**
* A {@link DataSource} for reading a raw resource inside the APK.
* 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
* <p>URIs supported by this source are of one of the forms:
* rawResourceId is the integer identifier of a raw resource. {@link #buildRawResourceUri(int)} can
*
* be used to build {@link Uri}s in this format.
* <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
{
public
final
class
RawResourceDataSource
extends
BaseDataSource
{
...
@@ -67,6 +79,7 @@ public final class RawResourceDataSource extends BaseDataSource {
...
@@ -67,6 +79,7 @@ public final class RawResourceDataSource extends BaseDataSource {
public
static
final
String
RAW_RESOURCE_SCHEME
=
"rawresource"
;
public
static
final
String
RAW_RESOURCE_SCHEME
=
"rawresource"
;
private
final
Resources
resources
;
private
final
Resources
resources
;
private
final
String
packageName
;
@Nullable
private
Uri
uri
;
@Nullable
private
Uri
uri
;
@Nullable
private
AssetFileDescriptor
assetFileDescriptor
;
@Nullable
private
AssetFileDescriptor
assetFileDescriptor
;
...
@@ -80,33 +93,55 @@ public final class RawResourceDataSource extends BaseDataSource {
...
@@ -80,33 +93,55 @@ public final class RawResourceDataSource extends BaseDataSource {
public
RawResourceDataSource
(
Context
context
)
{
public
RawResourceDataSource
(
Context
context
)
{
super
(
/* isNetwork= */
false
);
super
(
/* isNetwork= */
false
);
this
.
resources
=
context
.
getResources
();
this
.
resources
=
context
.
getResources
();
this
.
packageName
=
context
.
getPackageName
();
}
}
@Override
@Override
public
long
open
(
DataSpec
dataSpec
)
throws
RawResourceDataSourceException
{
public
long
open
(
DataSpec
dataSpec
)
throws
RawResourceDataSourceException
{
try
{
Uri
uri
=
dataSpec
.
uri
;
Uri
uri
=
dataSpec
.
uri
;
this
.
uri
=
uri
;
this
.
uri
=
uri
;
if
(!
TextUtils
.
equals
(
RAW_RESOURCE_SCHEME
,
uri
.
getScheme
()))
{
int
resourceId
;
throw
new
RawResourceDataSourceException
(
"URI must use scheme "
+
RAW_RESOURCE_SCHEME
);
if
(
TextUtils
.
equals
(
RAW_RESOURCE_SCHEME
,
uri
.
getScheme
())
}
||
(
TextUtils
.
equals
(
ContentResolver
.
SCHEME_ANDROID_RESOURCE
,
uri
.
getScheme
())
&&
uri
.
getPathSegments
().
size
()
==
1
int
resourceId
;
&&
Assertions
.
checkNotNull
(
uri
.
getLastPathSegment
()).
matches
(
"\\d+"
)))
{
try
{
try
{
resourceId
=
Integer
.
parseInt
(
Assertions
.
checkNotNull
(
uri
.
getLastPathSegment
()));
resourceId
=
Integer
.
parseInt
(
Assertions
.
checkNotNull
(
uri
.
getLastPathSegment
()));
}
catch
(
NumberFormatException
e
)
{
}
catch
(
NumberFormatException
e
)
{
throw
new
RawResourceDataSourceException
(
"Resource identifier must be an integer."
);
throw
new
RawResourceDataSourceException
(
"Resource identifier must be an integer."
);
}
}
}
else
if
(
TextUtils
.
equals
(
ContentResolver
.
SCHEME_ANDROID_RESOURCE
,
uri
.
getScheme
()))
{
transferInitializing
(
dataSpec
);
String
path
=
Assertions
.
checkNotNull
(
uri
.
getPath
());
AssetFileDescriptor
assetFileDescriptor
=
resources
.
openRawResourceFd
(
resourceId
);
if
(
path
.
startsWith
(
"/"
))
{
this
.
assetFileDescriptor
=
assetFileDescriptor
;
path
=
path
.
substring
(
1
);
if
(
assetFileDescriptor
==
null
)
{
}
throw
new
RawResourceDataSourceException
(
"Resource is compressed: "
+
uri
);
@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
());
}
else
{
this
.
inputStream
=
inputStream
;
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
());
inputStream
.
skip
(
assetFileDescriptor
.
getStartOffset
());
long
skipped
=
inputStream
.
skip
(
dataSpec
.
position
);
long
skipped
=
inputStream
.
skip
(
dataSpec
.
position
);
if
(
skipped
<
dataSpec
.
position
)
{
if
(
skipped
<
dataSpec
.
position
)
{
...
@@ -114,18 +149,21 @@ public final class RawResourceDataSource extends BaseDataSource {
...
@@ -114,18 +149,21 @@ public final class RawResourceDataSource extends BaseDataSource {
// skip beyond the end of the data.
// skip beyond the end of the data.
throw
new
EOFException
();
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
)
{
}
catch
(
IOException
e
)
{
throw
new
RawResourceDataSourceException
(
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
;
opened
=
true
;
transferStarted
(
dataSpec
);
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