Appearance
Release notes Web Framework 2
IMPORTANT
This version of the Colibrio Reader Framework is no longer covered by our warranty support.
2.2.0 2022-05-16
New features
- The TTS SyncMediaTimeline no longer adds the text "Media element" or "Image alt text" when a media element is encountered. Instead, when you call
ReaderPublication.createTtsSyncMediaTimeline(), you can set what text to prepend by setting the optioncontentTransformationOptions.imageAltTextPrefix.
Bug fixes
- Fixed an issue where PDF pages sometimes rendered as blank pages if the rendering was interrupted by a
ReaderView.refresh()orReaderView.setOptions(). - Fixed an issue where
IEngineEventMediaResource.getResourceUrl()could return incorrect URLs if loading the EPUB publication with aResourceProviderthat fetched resources over http, and itsgetBaseUrl()method returned an URL with the http scheme. - Calling
ReaderView.renderTo()with an element where its position style isstaticwill now cause it to set position torelativeas specified in the API docs. - Fixed an issue with
ContentPositionTimeline.fetchTimelineRangefor EPUB. When passing aContentLocationrange that ended just before a media element, the returned result incorrectly included the media element.
2.1.1 2022-03-21
Bug fixes
- Fixed an issue causing audio playback to break in some EPUBs on iOS/iPadOS 15.4.
- Fixed an issue that caused fixed-layout EPUBs to be rendered with the wrong aspect ratio if a
<meta name="viewport"..element contained extra whitespaces in its content attribute. - Fixed a bug that sometimes caused
IEngineEventMediaResource.createUrl()to generate invalid URLs. This method is typically used to create URLs for images to show them in full-screen when clicked.
2.1.0 2022-02-16
New features
- Added a new option
alignedSegmentSeekThresholdMstoISyncMediaAudioRendererOptions. This option controls how theSyncMediaAudioRenderershould treat gaps between two consecutive segments. If you hear many clicks, and cutoff words when playing back the audio in the publication, try increasing the value of this option.
Bug fixes
- Fixed an issue causing some links in PDF files to not work correctly.
- Fixed an issue in Safari/iOS where audio files would sometimes be skipped when playing EPUB Media Overlays.
- Fixed an issue in
URLUtils.getSubpath()that caused incorrect results for some URLs.
2.0.2 2022-01-12
New features
- You can now disable the pan/zoom reset when navigating a
ReaderViewby settingIReaderViewOptions.transformManagerOptions.removeTransformOnNavigationto false.
Bug fixes
- Fixed an issue that caused
IEpubReaderPublication.fetchContentLocation()to fail when passing a Locator selecting a range across multiple documents that started from the first ReaderDocument in the spine.
2.0.1 2021-11-30
Bug fixes
ResourceResponse.asText()now supports UTF-16 decoding. This adds support for EPUB resources encoded with UTF-16.
2.0.0 2021-11-09
Changes from 2.0.0-rc.6
Bug fixes
- Fixed an issue where
ReaderView.hasActiveTransform()returned wrong values. - Fixed an issue causing TrueType Collection fonts
.ttcfiles to not work with EPUB Publications. - Fixed an issue causing attribute selectors in CSS files to not work correctly.
Changes from 1.1.4
New features
This release contains the following major new features:
- ContentPositionTimeline API
- SingleDocumentScrollRenderer
- Media Streaming
- ResourceProvider API
- Keyboard EngineEvents
ContentPositionTimeline API
A ContentPositionTimeline is used for describing positions in ReaderPublication content as integers. The timeline starts at position 0 and its length can be retrieved using getLength().
The ContentPositionTimeline object provides an API for converting integer positions to ContentLocations, and vice versa.
The unit of measurement can be configured when creating a ContentPositionTimeline. Which units of measurement that are supported for a ReaderPublication can be retrieved using IReaderPublication.getAvailableContentPositionTimelineUnits().
For example:
- EPUB publications can construct
ContentPositionTimelines withCHARACTERSas the unit of measurement. A position is the character offset from the start of the publication. - PDF publications can construct
ContentPositionTimelineswithPAGESas the unit of measurement. A position is the page index from the start of the publication.
See EpubReaderPublication.createContentPositionTimeline(), PdfReaderPublication.createContentPositionTimeline() for how to create a ContentPositionTimeline.
As these timelines are constructed from publication content, a position in the timeline will always map to the same location in the publication content regardless of how the content is rendered. Thus, it is useful for implementing progress bars, reporting reading progression, etc.
See the API documentation for IContentPositionTimeline for more information.
SingleDocumentScrollRenderer
A new scrolling renderer is now available. It displays one document at the time and allows the user to scroll its content.
When a SyncMediaPlayer is attached to the ReaderView, the scroll position will automatically synchronize with the SyncMediaPlayer playback position.
You can read more about the SingleDocumentScrollRenderer and its behavior when using it together with SyncMedia in the developer guide.
Media Streaming
The framework now supports streaming of media resources using the browser's Media Source API. In this release, the framework can stream MP3 audio files. We plan to add support for AAC and MP4 in a future release.
While the <video> and <audio> elements support streaming over HTTP natively, when playing a media resource from an EPUB file, the complete file must first be extracted before playback can start. With media streaming enabled, the playback can start sooner.
Media streaming is an opt-in feature that can be enabled for media elements in EPUB publications, as well as for Media Overlays. It is recommended to enable this feature if you are streaming the EPUB file over the internet.
To enable it for media elements in EPUB publications, set IEpubReaderPublicationOptions.enableMediaStreaming to true. To enable it for Media Overlays, add the following option when creating the SyncMediaTimeline:
ts
epubReaderPublication.createMediaOverlaySyncMediaTimeline(readerDocuments, {
defaultAudioRendererOptions: {
enableMediaStreaming: true,
},
});Note that the enableMediaStreaming option has no effect on iOS devices since the Media Source API is not supported by that platform.
Keyboard events
You can now add EngineEvent listeners for "keydown" and "keyup" to detect keyboard events when the focus is inside publication content.
ResourceProvider API
The IResourceProvider has been completely refactored. Here are some of the improvements related to the new IResourceProvider type:
- The new
IResourceProviderworks much like the browser's Fetch API. This makes it a lot easier to create customIResourceProviderimplementations. This is for example useful when loading EPUBs usingEpubOcfResourceProvider.createFromBackingResourceProvider()to fetch resources from an already unzipped EPUB file. - Just like the Fetch API, the response from
IResourceProvider.fetch()contains aReadableStreamallowing the framework to start processing resources faster. - The new
IResourceProvidersupports Range Requests, allowing partial downloads of large files. This is for example used by the new Media Streaming feature. (Previously the resource provider would fetch entire resources, while theIRandomAccessDataSourceinterface allowed range requests when fetching chunks of the EPUB container.)
While it is possible to implement your own ResourceProvider, in most cases you should implement the IRandomAccessDataSource interface instead.
IRandomAccessDataSource
The return type of fetchChunk() has been changed to Promise<ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>>. By returning a Promise that resolves to a ReadableStream (like for example a response from fetch()), the framework is able to start processing the data faster.
Other features
EngineEventobjects for click events, pointer events and keyboard events now have the propertyengineEvent.target.frameworkComponent. This property can be used to detect if the target of the event was inside aReaderDocument, aReaderViewor aReaderViewAnnotation.EngineEventobjects for click events, pointer events and keyboard events now have the propertyengineEvent.willEmitDomEvent. Use this property to detect if a native DOM event will also be emitted in the app window. CallingpreventDefault()on theEngineEvent, or corresponding DOM event, will update thedefaultPreventedproperty on both event objects.- Added
IReaderPublicationOptions.clipboardOptionsallowing configuration of copy actions such as Ctrl+C. - Added
minimumTimeToDisplayPagesWithSyncMediatoISyncMediaManagedReaderViewSynchronizationOptions. - Added
alwaysSeekToSegmentStarttoISyncMediaManagedReaderViewSynchronizationOptions. - Added two new events
"contentPositionTimelineCreateProgress"and"syncMediaTimelineCreateProgress"that can be used to track the timeline creation progress. createContentPositionTimelineandcreateSyncMediaTimelinemethods now accept an optional third parameterprogressCallbackwhich can be used as an alternative to the events for receiving callbacks about the timeline creation progress.
Bug fixes
- Fixed a bug that caused the parsing of locator strings containing a
RangeSelectorto fail. (RangeSelectors are only used by the framework when creating locators across multiple pages in PDFs.) The bug did not affect highlight ranges in PDFs or EPUB CFI ranges. - Fixed several issues related to the
IContentLocationimplementation for PDF. - Rendering
ReaderViewAnnotationsfor PDF locators such as#page=2will now render a "position" element at the top-left corner. - Rendering
ReaderViewAnnotationsfor EPUB CFIs that pointed to the end of a container, i.e. after the last child in the container, will now render a "position" element at the closest point corresponding to the end of that container. - Fixed an issue where
ReaderView.hasActiveTransform()returned wrong values. - Fixed an issue causing TrueType Collection fonts
.ttcfiles to not work with EPUB Publications. - Fixed an issue causing attribute selectors in CSS files to not work correctly.
Improvements
- Improved performance in
SinglePageSwipeRendererandSpreadSwipeRenderer. - Improved rendering quality in
StackRendererandFlipbookRendereron Chrome. (See Breaking changes.) - Improved reflow performance.
FlipbookRendererandStackRendererUI has improved and now has more options to control shadows, perspective and rubber band effect when swiping at the beginning or the end of a publication.- Media downloading will now be aborted when it is no longer needed, for example if the user navigates to another location in the publication.
- The process of creating
SyncMediaTimelineandContentPositionTimelineinstances will now temporarily pause when: theReaderViewis performing a navigation, visible or offscreen content is rendering, or the user performs aReaderViewGesturesuch as swiping the page or pan-zooming.
Breaking changes
EngineEvents
In framework versions 0.x.x, EngineEvents such as "click" were only emitted if the click occurred inside the ReaderView element. However, in 1.x.x, EngineEvents such as "click" were fired even if an element outside the ReaderView was clicked. In 2.x.x, those EngineEvents are now again only fired if the ReaderView element or any child to it is the target of the event.
If you want to keep the behavior as it was in the 1.x.x version, set ReaderViewOptions.constrainEngineEventsToReaderView to false.
Regardless of this option, you can now use the property MouseEngineEvent.target.frameworkComponent to identify if the event was fired due to an interaction with your app, a ReaderDocument or a ReaderViewAnnotation.
FlipbookRenderer and StackRenderer
In an earlier version of the framework, a fix was added to workaround a bug on Chrome for Android. The bug causes content to sometimes disappear when performing pan-zoom gestures. The negative effect of enabling the bugfix was that zoomed-in content appeared blurry. Since the bug has not been observed since Chrome 90, we have now removed it in order to improve rendering quality. If the bug should resurface, you can enable the bugfix again by setting the renderer option fixDisappearingCharactersInChromeForAndroid to true.
FlipBookRenderer does no longer show an empty page before the first page of the publication by default. This behavior can be reverted by setting IFlipBookRendererOptions.hideEmptySpreadSlots to false.
Full list of breaking changes
Most of the changes below are related to the refactoring of the IResourceProvider type. Unless you have created your own IResourceProvider implementation for use with the EpubOcfResourceProvider.createFromBackingResourceProvider(), upgrading from 1.x.x to 2.0.0 should have very little impact on your code.
colibrio-core-drm
DrmManager:
- The constructor has changed.
getDecryptedResource()has been replaced withgetDecryptedResourceMetadata()andgetDecryptedResourceResponse().isEncrypted()has changed.
IEncryptionMethod:
decrypt()has changed.
colibrio-core-io-base
IResourceProvider has been completely refactored:
getResource()has been removed.- Added
fetch(),fetchMetadata(),getResourceManifest()andisUrlSupportedByBrowser().
ArrayInputStream has been removed.
BlobUrlManager:
createUrl()has changed.
InvalidResource has been removed. Use ErrorResourceResponse instead.
MediaTypeCategory enum values have changed.
IInputStream has been removed.
IResourceDataStream has been removed. (Data streams now use the browser's ReadableStream API.)
IResource has been removed.
IResourceMetadata has been removed.
IResourceMetadataJson has been renamed to IResourceMetadata.
IRandomAccessDataSource:
fetchChunk()can now return more types:Promise<ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>>.
colibrio-core-io-resourceprovider-cache
This module has been completely removed. It has been replaced by colibrio-core-io-resourcecache which is a new implementation no longer implementing the IResourceProvider interface.
colibrio-core-io-resourceprovider-zip
ZipResourceProvider now implements the new IResourceProvider.
colibrio-core-publication-epub
EpubOcfResourceProvider now implements the new IResourceProvider.
createFromBackingResourceProvider()has changed.IEpubResourceProviderhas been removed.
IEpubPublication:
fetchMediaOverlay()has changed.getCoverImageResource()has been replaced bygetCoverImageUrl().
colibrio-readingsystem-base
Prior to this release, palette and fontset from PublicationStyleOptions were applied to fixed-layout documents, breaking the design of many fixed-layout EPUBs. These customizations are now disabled for fixed-layout documents by default and can be enabled using IReaderPublicationOptions.fixedLayoutStyleOptions.
NavigationAction:
NEXThas been split intoNEXT_CONTENT_RANGEandNEXT_RENDERABLE_PAGE.PREVIOUShas been split intoPREVIOUS_CONTENT_RANGEandPREVIOUS_RENDERABLE_PAGE.
IEngineEventMediaResource:
getMediaType()has been removed.
IReaderViewAnnotation:
isInView()has been renamed toisIntersectingVisibleRange().
colibrio-readingsystem-renderer
ContinuousScrollRenderer has been removed. (In 1.0.0 we included an early proof-of-concept version by mistake.)
ScrolledDocumentRenderer has been renamed to SingleDocumentScrollRenderer and is now officially supported.
1.1.4 2021-10-07
Bug fixes
- Fixed an issue where
ReaderView.getActiveGestureType()always returned null. Note that the event"activeGestureTypeChanged"still contained correct values.
1.1.3 2021-09-13
Bug fixes
- Fixed an issue where EPUB
ReaderDocuments failed to render if it had a CSS file that ended with an open comment, i.e. a comment that was not closed with*/.
1.1.2 2021-09-06
Bug fixes
- Fixed an issue where
PageProgressionTimelinereported wrong page number if the page was (intentionally) blank. - The CSS parser now escapes special characters in identifiers correctly.
- Fixed an issue that in some cases could cause EPUB pages to appear "frozen". This caused swipe gestures, CSS animations etc. to not work.
1.1.1 2021-06-22
Bug fixes
- Fixed an issue that caused
SelectorTypeto not be exported correctly. - Fixed an issue that caused
ReaderViewAnnotations to not render if the backing EPUB CFI pointed to the end of an element. - Fixed an issue that caused CSS variables to not be preserved in publication stylesheets.
- Fixed an issue that could cause EPUB Media Overlays to not play correctly if the
"src"attribute in a<text>element did not contain a fragment identifier (i.e. it referenced the whole document).
1.1.0 2021-05-26
New features
- The semver version string of the framework can now be retrieved using
ReadingSystemEngine.getFrameworkVersion().
Bug fixes
- Fixed an issue with
ContentLocation.isAfter()andContentLocation.isBefore()returning incorrect values in some cases for EPUB publications. - Fixed an issue that caused
ReaderViewGestures to not work correctly ifsetAllowedGestureTypes()was called while a gesture was active. - Fixed an issue where the
SyncMediaPlayerdid not automatically navigate to next page if the remaining pages in theReaderViewdid not contain sync media. - Fixed an issue in
WebSpeechTtsSynthesizerwhere segments longer than 15 seconds would causespeechSynthesizerto stop working due to a Chrome bug. - Fixed an issue where the
ReaderViewdid not remove the active renderer correctly when switching to content set bysetContentOnActiveRendererMissing(). - Fixed an issue where
ReaderView.focusOnReadingPosition()sometimes could fail with an unexpectedTypeErrorin EPUB publications.
1.0.0 2021-05-05
Bug fixes
- Fixed an issue that could cause EPUB Media Overlay to not work properly when a
<par>node referenced thebodyelement.
1.0.0-beta.7 2021-04-06
New features
- Added new options to
PdfPublicationOptionsto enable chunk requests with deterministic sizes.
Bug fixes
- Fixed an issue that could cause the
SyncMediaPlayerto pause in some cases when segment duration was 0.
1.0.0-beta.6 2021-03-15
Bug fixes
- Fixed an issue causing the
SyncMediaPlayerto fail advancing to next segment sometimes when playing VBR (variable bitrate) audio files like MP3 or AAC, and the MediaOverlay used aclipEndvalue greater than the actual audio file duration.
1.0.0-beta.5 2021-03-11
Bug fixes
- Fixed an issue where documents with non-standard media type
application/htmlcouldn't be loaded properly. - Fixed an issue causing scripts in scripted content documents to sometimes load in the wrong order if the script was loaded over https.
- Fixed an issue where
SyncMediaPlayersometimes did not play the last seconds of VBR (Variable bitrate) AAC audio files.
1.0.0-beta.4 2021-03-01
Bug fixes
- Fixed an issue where
FlipBookRendererandSpreadSwipeRendererdid not handle publications with RTL page progression direction correctly.
1.0.0-beta.3 2021-02-26
New features
- The
'syncMediaError'engine event now contains more information about the error, and if the player was paused due to the error. IReaderPublication.fetchContentLocationwas added.- The TTS implementation has been refactored. The new implementation has more accurate mappings between
ISyncMediaTimelinePositions andIContentLocations, and adds support for highlighting of the word that is being spoken. The methodsEpubReaderPublication.createTtsSyncMediaTimelineandPdfReaderPublication.createTtsSyncMediaTimelinehave changed to support those changes.
Breaking changes
- Removed the option
IPaginatedRendererOptions.prerenderOffscreenPages. Offscreen pages will now always be pre-rendered. ILocatorFactory.parse()andILocatorFactory.createRangeLocator()now return anILocatorParseResultwith either the newLocatorinstance or an error describing what caused the parsing to fail.ILoggerlog methods now support an arbitrary number of arguments (like the browser console log methods).
Bug fixes
- Fixed an issue causing AAC audio files to not work sometimes on Safari (iOS, iPadOS, Mac).
- Fixed an issue that could cause the
SyncMediaPlayerto start playing from start of the timeline a short period of time while performing the initialReaderView.goTo. IReaderViewAnnotationOptionscan now be used to override positioning and dimensions (width/height, left/top, etc.).- Fixed an issue where large widths specified on elements in EPUB content documents caused font-size to decrease.
- The
syncMediaEndReachedevent should now fire correctly.
1.0.0-beta.2 2020-02-04
Bug fixes
- Re-added the method
IReaderDocument.fetchLocatorFromContentBlockData()to be able to getLocators for search results using the legacy index engine API. - Removed
TypedJsonObjecttype as it caused errors with Typescript 4.0 and 4.1. - Fixed an issue causing
WebSpeechTtsSynthesizerto not work in MacOS/Safari. - Improved EPUB resource streaming to prevent timeout errors when downloading large files over slow internet connections.
- Refreshing the
ReaderViewwhile performing a next/previous animation will now result in the reading position being properly updated to the next/previous page. ReaderView.goTo()navigations to adjacent pages will now use the next/previous animations.- Fixed a memory leak related to doing many
goTos in rapid succession.
1.0.0-beta.1 2020-01-25
Bug fixes
- Added a processing step to rewrite large horizontal margins that caused content to overflow horizontally on small screens.
1.0.0-alpha.36 2020-01-12
Breaking changes
ResolvedReaderPublicationLocationTargetwas renamed toContentLocation.ReaderPublicationLocationTargetwas renamed toUnresolvedContentLocation.- All properties referring to
locationTargetshave now been renamed tocontentLocation. ReaderViews must now be destroyed fromReadingSystemEngine.ContentLocation.fetchContentBlockTarget()method signature has changed.
Bug fixes
- Fixed an issue with
TtsSyncMediaTimeline.fetchTimelinePosition()returning incorrect positions for some Locators. - Fixed an issue in
SyncMediaPlayer.attemptReaderViewSynchronization()causing uncaught promise to be logged if synchronization failed. - Fixed several issues with the
WebSpeechTtsSynthesizercausing TTS to fail after a while in Chrome and Firefox. - Fixed an issue causing
AnnotationLayers to sometimes not render the annotations for the current visible page(s) if the annotations were added immediately after creating theAnnotationLayer.
1.0.0-alpha.35 2020-12-11
Bug fixes
- Fixed an issue causing pointer events and text selection in PDFs to not work as expected.
- Fixed an issue causing gestures such as swiping between pages to not work if starting the gesture outside page content.
1.0.0-alpha.34 2020-12-02
New features
- Added
ReaderView.focusOnReadingPosition. By focusing on publication content, your app gives accessibility technologies such as screen readers an intent where to start reading. For more information, see API docs and demo app. - Added two new options to
IFlipBookRendererOptions:showPageFoldShadowandpageFoldShadowOpacity. SettingshowPageFoldShadowto true will add a shadow between the left and right page, making it look more like a book. - Added support for CSS declarations
object-fitandobject-positionin reflowable content documents. These allow you to control how to position images that have been scaled. - Added improved support for range locators. Range locators can now point to ranges across multiple documents in a publication.
ReaderViewand Renderers has been reworked to support more advanced presentation modes.
Bug fixes
- Video elements should now be allowed to play in fullscreen. Caveat: When rotating the screen on iOS,
view.refresh()will exit fullscreen mode. - Ensure that error responses from
RandomAccessDataSourceare not cached by theZipResourceProviderso that they can be retried. - Fixed an issue where Chrome caused reflowable documents containing soft-hyphen characters to page-break at incorrect positions.
- Fixed an issue when reflowing EPUBs that in some cases caused too much content to appear on a single page.
1.0.0-alpha.33
New features
- Publication metadata now available for all publication types.
- You can now override text alignment in reflowable content documents using the
textAlignmentproperty inPublicationStyleOptions.
Improvements
- Prevent loading CSS background-images that are included in the stylesheet but not used in the active content document.
Bug fixes
- Fixed an issue where illegal attribute values for
widthorheighton<img>elements could cause images to appear stretched.
1.0.0-alpha.32
Breaking changes
- Enum
RendererDirectionhas been replaced with the more genericAxis. This caused changes to the following types:SinglePageSwipeRendererOptions,SpreadSwipeRendererOptions.
Improvements
- Allow
data-attributes in EPUB content documents. - Ensure remote images and videos behave correctly when reflowing content.
Bug fixes
- Fixed an issue causing
'click'events to not fire on iOS 12 and earlier in some publications. - Fixed an issue causing
FlipBookRendererandStackRendererto animate incorrectly in some cases. - Fixed an issue where reflowing content documents containing CSS
position: relativecaused page breaks to occur too early.
1.0.0-alpha.31
Improvements
- Added
"object"tag to EPUB html element whitelist in order to support "EPUB3 bindings" fallback content. - Added support for
@importdeclarations in CSS files.
Bug fixes
- Fixed an issue causing fonts in EPUBs to not load correctly in some cases if the wrong media type was used in the OPF file.
- Fixed an issue causing the EPUB
FileSizeBasedpage estimation algorithm to report inaccurate results for some EPUBs. - Force video files with the
.m4vextension to use the media-type"video/mp4"in order for playback to work in Safari browsers.
1.0.0-alpha.30
New features
- In previous versions of the framework, the Page Progression Timeline was recalculated while visible pages were being rendered. For some EPUBs this caused a significant delay until pages were rendered and users could start reading. From this version, Page Progression Timeline recalculations are performed after first visible pages has rendered. This reduces time until users see content on-screen. You can opt-out of this behavior by setting the view option
pageProgressionTimelineOptions.delayRecalculationUntilPagesVisibleto false. EpubCharacterPageCountEstimationAlgorithm: Media elements and IFrames are now counted as characters. The amount of characters per element is configurable.
Breaking changes
PublicationStyleOptions:pageMarginHorizontalandpageMarginVerticalhave been replaced withpageMargins. This allows you to specify page margins per side and in other units than percentage.EpubReaderPublicationOptions:pageCountEstimationAlgorithmnow takes an object allowing further configuration per algorithm type.
Bug fixes
- Fixed an issue that sometimes caused zoom-out gestures to not work properly while in TRANSFORM state.
- Fixed an issue causing palette options to not work in some EPUBs.
- Fixed an issue causing wrong background color being used for page margins in some EPUBs.
- Fixed an issue causing click events to not work as intended on iOS < 13 in scripted content documents.
- Fixed an issue causing pointer events to not work as intended when using 2 or more pointers (such as pinch-zoom gestures).
Improvements
- Improved performance when using
EpubPageCountEstimationAlgorithmType.CHARACTERSas page estimation algorithm for EPUB. - Improved accessibility support for VoiceOver (iOS) and Talkback (Android).