You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+51-3Lines changed: 51 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,17 +6,65 @@ All notable changes to this project will be documented in this file. Take a look
6
6
7
7
## [Unreleased]
8
8
9
+
:warning: Please consult [the migration guide](docs/migration-guide.md#300-alpha1) to assist you in handling the breaking changes in this latest major release.
10
+
9
11
### Added
10
12
13
+
#### Shared
14
+
15
+
* A new `Format` type was introduced to augment `MediaType` with more precise information about the format specifications of an `Asset`.
16
+
* The `DownloadManager` interface handles HTTP downloads. Components like the `LcpService` rely on it for downloading publications. Readium v3 ships with two implementations:
17
+
*`ForegroundDownloadManager` uses an `HttpClient` to download files while the app is running.
18
+
*`AndroidDownloadManager` is built upon [Android's `DownloadManager`](https://developer.android.com/reference/android/app/DownloadManager) to manage HTTP downloads, even when the application is closed. It allows for resuming downloads after losing connection.
19
+
* The default `ZipArchiveOpener` now supports streaming ZIP archives, which enables opening a packaged publication (e.g. EPUB or LCP protected audiobook):
20
+
* served by a remote HTTP server,
21
+
* accessed through an Android `ContentProvider`, such as the shared storage.
22
+
11
23
#### Navigator
12
24
13
25
* Support for keyboard events in the EPUB, PDF and image navigators. See `VisualNavigator.addInputListener()`.
14
26
15
-
###Fixed
27
+
#### LCP
16
28
17
-
#### OPDS
29
+
* You can now stream an LCP protected publication using its LCP License Document. This is useful for example to read a large audiobook without downloading it on the device first.
30
+
* The hash of protected publications is now verified upon download.
31
+
32
+
### Changed
33
+
34
+
*:warning: To avoid conflicts when merging your app resources, all resources declared in the Readium toolkit now have the prefix `readium_`. This means that you must rename any layouts or strings you have overridden. Some resources were removed from the toolkit. Please consult [the migration guide](docs/migration-guide.md#300-alpha1).
35
+
* Most APIs now return an `Error` instance instead of an `Exception` in case of failure, as these objects are not thrown by the toolkit but returned as values
36
+
37
+
#### Shared
38
+
39
+
*:warning: To improve the interoperability with other Readium toolkits (in particular the Readium Web Toolkits, which only work in a streaming context) **Readium v3 now generates and expects valid URLs** for `Locator` and `Link`'s `href`. **You must migrate the HREFs or Locators stored in your database**, please consult [the migration guide](docs/migration-guide.md#300-alpha1).
40
+
*`Link.href` and `Locator.href` are now respectively `Href` and `Url` objects. If you still need the string value, you can call `toString()`
41
+
*`MediaType` no longer has static helpers for sniffing it from a file or URL. Instead, you can use an `AssetRetriever` to retrieve the format of a file.
42
+
43
+
#### Navigator
44
+
45
+
* Version 3 includes a new component called `DirectionalNavigationAdapter` that replaces `EdgeTapNavigation`. This helper enables users to navigate between pages using arrow and space keys on their keyboard or by tapping the edge of the screen.
46
+
* The `onTap` and `onDrag` events of `VisualNavigator.Listener` have been deprecated. You can now use multiple implementations of `InputListener` with `VisualNavigator.addInputListener()`.
47
+
48
+
#### Streamer
49
+
50
+
* The `Streamer` object has been deprecated in favor of components with smaller responsibilities: `AssetRetriever` and `PublicationOpener`.
51
+
52
+
#### LCP
53
+
54
+
*`LcpService.acquirePublication()` is deprecated in favor of `LcpService.publicationRetriever()`, which provides greater flexibility thanks to the `DownloadManager`.
55
+
* The way the host view of a `LcpDialogAuthentication` is retrieved was changed to support Android configuration changes.
56
+
57
+
### Deprecated
58
+
59
+
* Both the Fuel and Kovenant libraries have been completely removed from the toolkit. With that, several deprecated functions have also been removed.
60
+
61
+
#### Shared
62
+
63
+
* The `putPublication` and `getPublication` helpers in `Intent` are deprecated. Now, it is the application's responsibility to pass `Publication` objects between activities and reopen them when necessary.
64
+
65
+
#### Navigator
18
66
19
-
*Fixed race conditions causing `ConcurrentModificationException`to be thrown when parsing an OPDS 2 feed.
67
+
*EPUB external links are no longer handled by the navigator. You need to open the link in your own Web View or Chrome Custom Tab.
:warning: The described components are is still experimental.
3
+
:warning: The APIs described here may still undergo changes before the stable 3.0 release.
4
4
5
-
Readium requires you to instantiate a few components before you can actually open a publication.
5
+
To open a publication with Readium, you need to instantiate a couple of components: an `AssetRetriever` and a `PublicationOpener`.
6
6
7
-
## Constructing an `AssetRetriever`
7
+
## `AssetRetriever`
8
8
9
-
First, you need to instantiate an `HttpClient` to provide the toolkit the ability to do HTTP requests.
10
-
You can use the Readium `DefaultHttpClient` or a custom implementation. In the former case, its callback will
11
-
enable you to perform authentication when required.
12
-
Then, you can create an `AssetRetriever` which will enable you to read content through different schemes and guess its format.
13
-
In addition to an `HttpClient`, the `AssetRetriever` constructor takes a `ContentResolver` to support data access through the `content` scheme.
9
+
The `AssetRetriever` grants access to the content of an asset located at a given URL, such as a publication package, manifest, or LCP license.
10
+
11
+
### Constructing an `AssetRetriever`
12
+
13
+
You can create an instance of `AssetRetriever` with:
14
+
15
+
* A `ContentResolver` to support data access through the `content` URL scheme.
16
+
* An `HttpClient` to enable the toolkit to perform HTTP requests and support the `http` and `https` URL schemes. You can use `DefaultHttpClient` which provides callbacks for handling authentication when needed.
14
17
15
18
```kotlin
16
19
val httpClient =DefaultHttpClient()
17
-
18
20
val assetRetriever =AssetRetriever(context.contentResolver, httpClient)
19
21
```
20
22
21
-
##Constructing a `PublicationOpener`
23
+
### Retrieving an `Asset`
22
24
23
-
The component which can parse an `Asset` giving access to a publication to build a `Publication`
24
-
object is the `PublicationOpener`. Its constructor requires you to pass in:
25
+
With your fresh instance of `AssetRetriever`, you can open an `Asset` from an `AbsoluteUrl`.
25
26
26
-
* a `PublicationParser` it delegates the parsing work to.
27
-
* a list of `ContentProtection`s which will deal with DRMs.
27
+
```kotlin
28
+
// From a `File`
29
+
val url =File("...").toUrl()
30
+
// or from a content:// `Uri`
31
+
val url = contentUri.toAbsoluteUrl()
32
+
// or from a raw URL string
33
+
val url =AbsoluteUrl("https://domain/book.epub")
34
+
35
+
val asset = assetRetriever.retrieve(url)
36
+
.getOrElse { /* Failed to retrieve the Asset */ }
37
+
```
28
38
29
-
The easiest way to get a `PublicationParser` is to use the `DefaultPublicationParser` class. As to
30
-
`ContentProtection`s, you can get one to support LCP publications through your `LcpService` if you have one.
39
+
The `AssetRetriever` will sniff the media type of the asset, which you can store in your bookshelf database to speed up the process next time you retrieve the `Asset`. This will improve performance, especially with HTTP URL schemes.
40
+
41
+
```kotlin
42
+
val mediaType = asset.format.mediaType
43
+
44
+
// Speed up the retrieval with a known media type.
45
+
val asset = assetRetriever.retrieve(url, mediaType)
46
+
```
47
+
48
+
## `PublicationOpener`
49
+
50
+
`PublicationOpener` builds a `Publication` object from an `Asset` using:
51
+
52
+
* A `PublicationParser` to parse the asset structure and publication metadata.
53
+
* The `DefaultPublicationParser` handles all the formats supported by Readium out of the box.
54
+
* An optional list of `ContentProtection` to decrypt DRM-protected publications.
55
+
* If you support Readium LCP, you can get one from the `LcpService`.
31
56
32
57
```kotlin
33
58
val contentProtections =listOf(lcpService.contentProtection(authentication))
@@ -37,34 +62,25 @@ val publicationParser = DefaultPublicationParser(context, httpClient, assetRetri
37
62
val publicationOpener =PublicationOpener(publicationParser, contentProtections)
38
63
```
39
64
40
-
##Bringing the pieces together
65
+
### Opening a `Publication`
41
66
42
-
Once you have got an `AssetRetriever` and a `PublicationOpener`, you can eventually open a publication as follows:
43
-
```kotlin
44
-
val asset = assetRetriever.open(url, mediaType)
45
-
.getOrElse { return error }
67
+
Now that you have a `PublicationOpener` ready, you can use it to create a `Publication` from an `Asset` that was previously obtained using the `AssetRetriever`.
46
68
47
-
val publication = publicationOpener.open(asset)
48
-
.getOrElse { return error }
49
-
```
69
+
The `allowUserInteraction` parameter is useful when supporting Readium LCP. When enabled and using a `LcpDialogAuthentication`, the toolkit will prompt the user if the passphrase is missing.
50
70
51
-
Persisting the asset media type on the device can significantly improve performance as it is strong hint
52
-
for the content format, especially in case of remote publications.
71
+
```kotlin
72
+
val publication = publicationOpener.open(asset, allowUserInteraction =true)
73
+
.getOrElse { /* Failed to access or parse the publication */ }
74
+
```
53
75
54
76
## Supporting additional formats or URL schemes
55
77
56
-
`DefaultPublicationParser` accepts additional parsers. You can also use your own parser list
57
-
with `CompositePublicationParser` or implement [PublicationParser] in the way you like.
58
-
59
-
`AssetRetriever` offers an alternative constructor providing better extensibility in a similar way.
60
-
This constructor takes several parameters with different responsibilities.
61
-
62
-
*`ResourceFactory` determines which schemes you will be able to access content through.
63
-
*`ArchiveOpener` which kinds of archives your `AssetRetriever` will be able to open.
64
-
*`FormatSniffer` which file formats your `AssetRetriever` will be able to identify.
78
+
`DefaultPublicationParser` accepts additional parsers. You also have the option to use your own parser list by using `CompositePublicationParser` or create your own `PublicationParser` for a fully customized parsing resolution strategy.
65
79
66
-
For each of these components, you can either use the default implementations or implement yours
67
-
with the composite pattern. `CompositeResourceFactory`, `CompositeArchiveOpener` and `CompositeFormatSniffer`
68
-
provide simple implementations trying every item of a list in turns.
80
+
The `AssetRetriever` offers an additional constructor that provides greater extensibility options, using:
69
81
82
+
*`ResourceFactory` which handles the URL schemes through which you can access content.
83
+
*`ArchiveOpener` which determines the types of archives (ZIP, RAR, etc.) that can be opened by the `AssetRetriever`.
84
+
*`FormatSniffer` which identifies the file formats that `AssetRetriever` can recognize.
70
85
86
+
You can use either the default implementations or implement your own for each of these components using the composite pattern. The toolkit's `CompositeResourceFactory`, `CompositeArchiveOpener`, and `CompositeFormatSniffer` provide a simple resolution strategy.
0 commit comments