Skip to content

Commit

Permalink
Nam/v1/sample tiktok (#82)
Browse files Browse the repository at this point in the history
* init tiktok demo

* Fix a log type

* Remove unused imports

* Do not init cookie manager from the library

* Remove default parameter values from KohiiExoPlayer

* Include Playback value in the artwork hint callback

* Minor change

* Update changelog

* Minor improvement

* Support Playback locking

* Minor improvement

* Support Playback locking.

* Updating to use buildFeatures

* Update lock/unlock method

* Update lock/unlock methods

* Update readme and changelog

* Add a convenient "get" method to the Capsule

* Add base implementation for the ExoPlayerProvider

* Add convenient Cache creators

* Add default value to KohiiExoPlayer constructor

* Update

* Add global convenient creators for Kohii

* Add `ExoPlayerConfig` for advance use cases.

* Update

* Update changelog

* Update locking mechanism.

* Update locking mechanism

* Update navigation component version to 2.3.0 rc1

* Update TikTok demo

* Update changelog

* Update changelog

* Docs: update the glossary

* Minor fix

* Remove unused methods

* More power for the ExoPlayerConfig

* Various changes for the ExoPlayerProvider construction.

* Update document

* Update document
  • Loading branch information
eneim committed Jun 21, 2020
1 parent beb8a92 commit a38d93a
Show file tree
Hide file tree
Showing 104 changed files with 2,796 additions and 391 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Expand Up @@ -80,3 +80,7 @@
/.idea/markdown-navigator-enh.xml
/.idea/jarRepositories.xml
/.idea/render.experimental.xml
/.idea/navEditor.xml
/kohii-sample-tiktok/libs/
/kohii-sample-tiktok/src/androidTest/
/kohii-sample-tiktok/src/test/
9 changes: 9 additions & 0 deletions CHANGELOG.md
Expand Up @@ -15,12 +15,21 @@ _Under development_
- Add method `Kohii.createControlDispatcher(Playback)`.
- Add method `Playback.Controller.setupRenderer(Playback, Any?)`.
- Add method `Playback.Controller.teardownRenderer(Playback, Any?)`.
- Support Playback locking: if a Playback is locked, it will still be selected but will not be played.
- Add `ExoPlayerCache` to the `kohii-exoplayer` package. It can be used to obtain a pre-built Cache easily.
- Add `ExoPlayerConfig` to gather most of the detailed setting for a `SimpleExoPlayer` instance.
- Add `TrackSelectorFactory`, `LoadControlFactory`.
- Add `createKohii` convenient methods to easily create `Kohii` instance with custom parameters.
- Add `Engine.lock*` and `Engine.unlock*` methods to support manual lock/unlock an Activity/Manager/Bucket or Playback.
- Add a simple demonstration that builds TikTok-alike UI/UX.

- [Breaking] Rename `Playable#considerRequestRenderer` -> `Playable#setupRenderer`.
- [Breaking] Rename `Playable#considerReleaseRenderer` -> `Playable#teardownRenderer`.
- [Breaking] `RendererProvider#releaseRenderer` now needs to return a boolean.
- [Breaking] `Playback#addCallback` and `Playback#removeCallback` are now internal.
- [Breaking] The `DefaultControlDispatcher` is now internal.
- [Breaking] Include Playback in the `ArtworkHintListener#onArtworkHint`.
- [Breaking] Remove default implementations for `BandwidthMeterFactory`.

## 1.0.0.2010004

Expand Down
12 changes: 12 additions & 0 deletions README.md
Expand Up @@ -45,6 +45,18 @@ implementation "im.ene.kohii:kohii-exoplayer:1.0.0.2010004" // default support f
implementation "com.google.android.exoplayer:exoplayer:2.10.4" // required ExoPlayer implementation.
```

You will need to set this flag to your build.gradle too: `-Xjvm-default=enable`.

```groovy
android {
kotlinOptions {
freeCompilerArgs += [
'-Xjvm-default=enable'
]
}
}
```

## Start a playback

```Kotlin tab=
Expand Down
3 changes: 3 additions & 0 deletions build.gradle
Expand Up @@ -48,6 +48,9 @@ allprojects {
jcenter()
maven { url 'https://jitpack.io' }
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
flatDir {
dirs 'libs'
}
}

apply plugin: "org.jlleitschuh.gradle.ktlint" // Version should be inherited from parent
Expand Down
20 changes: 11 additions & 9 deletions buildSrc/src/main/java/kohii/Dependencies.kt
Expand Up @@ -76,7 +76,7 @@ object Libs {
// 0.10.0 render method signature after the doc, which looks pretty bad.
const val dokkaPlugin = "org.jetbrains.dokka:dokka-android-gradle-plugin:0.9.18"

val junit = "junit:junit:4.12"
val junit = "junit:junit:4.13"
val junitExt = "androidx.test.ext:junit-ktx:1.1.1"
val robolectric = "org.robolectric:robolectric:4.3.1"
val mockitoKotlin = "com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0"
Expand All @@ -103,6 +103,8 @@ object Libs {
val palette = "androidx.palette:palette-ktx:1.0.0"
val emoji = "androidx.emoji:emoji:1.0.0"

val vector = "androidx.vectordrawable:vectordrawable:1.1.0"

val recyclerView = "androidx.recyclerview:recyclerview:1.1.0"
val recyclerViewSelection = "androidx.recyclerview:recyclerview-selection:1.1.0-rc01"

Expand All @@ -121,7 +123,7 @@ object Libs {
}

object Navigation {
private const val version = "2.2.1"
private const val version = "2.3.0-rc01"

val runtimeKtx = "androidx.navigation:navigation-runtime-ktx:$version"
val commonKtx = "androidx.navigation:navigation-common-ktx:$version"
Expand All @@ -131,24 +133,24 @@ object Libs {
}

object Fragment {
private const val version = "1.2.1"
private const val version = "1.2.4"
val fragment = "androidx.fragment:fragment:$version"
val fragmentKtx = "androidx.fragment:fragment-ktx:$version"
}

object Test {
private const val version = "1.2.0"
private const val version = "1.3.0-rc01"
val core = "androidx.test:core:$version"
val runner = "androidx.test:runner:$version"
val rules = "androidx.test:rules:$version"

val espressoCore = "androidx.test.espresso:espresso-core:3.2.0-beta01"
val espressoCore = "androidx.test.espresso:espresso-core:3.3.0-rc01"
}

val archCoreTesting = "androidx.arch.core:core-testing:2.1.0"

object Paging {
private const val version = "2.1.1"
private const val version = "2.1.2"
val common = "androidx.paging:paging-common-ktx:$version"
val runtime = "androidx.paging:paging-runtime-ktx:$version"
}
Expand All @@ -158,8 +160,8 @@ object Libs {
// beta4 breaks the overlay demo ...
val constraintLayout = "androidx.constraintlayout:constraintlayout:2.0.0-beta3"

val core = "androidx.core:core:1.2.0"
val coreKtx = "androidx.core:core-ktx:1.2.0"
val core = "androidx.core:core:1.3.0"
val coreKtx = "androidx.core:core-ktx:1.3.0"

object Lifecycle {
private const val version = "2.2.0"
Expand All @@ -174,7 +176,7 @@ object Libs {
}

object Room {
private const val version = "2.2.3"
private const val version = "2.2.5"
val common = "androidx.room:room-common:$version"
val runtime = "androidx.room:room-runtime:$version"
val compiler = "androidx.room:room-compiler:$version"
Expand Down
71 changes: 71 additions & 0 deletions docs/advance-builder.md
@@ -0,0 +1,71 @@
## Using Builder

**Kohii** instance can be constructed using `Builder`. By default, calling `Kohii[context]` will create or reuse an instance with default implementation. For advance users, it is more flexible to be able to customize this. **Kohii** provides `Builder` to make this happen:

```Kotlin tab=
val playableCreator = MyCustomPlayableCreator()
val builder = Kohii.Builder(context)
.setPlayableCreator(playableCreator)
val kohii = builder.build()
```

```Java tab=
PlayableCreator<PlayerView> playableCreator = new MyCustomPlayableCreator();
Kohii.Builder builder = new Kohii.Builder(context)
.setPlayableCreator(playableCreator);
Kohii kohii = builder.build();
```

If you still want to use the default `PlayerViewPlayableCreator`, it can be constructed by its own Builder too, which will requires a `PlayerViewBridgeCreatorFactory` which is of type `(Context) -> BridgeCreator<PlayerView>`:

```Kotlin tab=
val playableCreator: PlayableCreator<PlayerView> =
PlayerViewPlayableCreator.Builder(this)
.setBridgeCreatorFactory(myFactory).build()
```

A full Kohii example:

```kotlin
val kohii = Kohii.Builder(context)
.setPlayableCreator(
PlayerViewPlayableCreator.Builder(context)
.setBridgeCreatorFactory {
PlayerViewBridgeCreator(myPlayerProvider, myMediaSourceFactoryProvider)
}
.build()
)
.setRendererProviderFactory(myFactory)
.build()
```

Please take a look at the source for all available builder parameters.

## Using extension methods

_From v1.1.0.2011003_

You also have more advance ways to construct new **Kohii** instance:

```kotlin
val kohii = createKohii(
context = context,
config = ExoPlayerConfig.DEFAULT
)
```

Where [ExoPlayerConfig](../api/kohii-exoplayer/kohii.v1.exoplayer/-exo-player-config/) is the combination of many base parameters to construct ExoPlayer's components like the `LoadControl`, `DefaultTrackSelector`, `DefaultBandwidthMeter`, etc. If you have existing parameter to reuse, you can use this convenient to build a **Kohii** instance using them. `ExoPlayerConfig.DEFAULT` is the default configuration where the parameters are the same as default ExoPlayer's setup.

If you want to reuse the already-built ExoPlayer components (`LoadControl`, `DefaultTrackSelector`, `DefaultBandwidthMeter`, etc) instead, you can also use the second convenient creator below:

```kotlin
val kohii = createKohii(
context = context,
playerCreator = myPlayerCreator,
mediaSourceFactoryCreator = myMediaSourceFactoryCreator,
rendererProviderFactory = myFactory
)
```

Using this method, you can pass your custom way of creating a new [Player](https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/Player.html) instance,
[MediaSourceFactory](https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/source/MediaSourceFactory.html) instance and [RendererProvider](../api/kohii-core/kohii.v1.core/-renderer-provider/) instance. Each parameter comes with a default value.
1 change: 1 addition & 0 deletions docs/advance-manual-playback.md
@@ -0,0 +1 @@
_Coming Soon_
@@ -1,6 +1,6 @@
## Using MemoryMode to improve UX

Your screen may contain many Videos at a time, and preload Videos forward so they can start as soon as possible is a legit requirement. In practice, preloading Videos consumes a lot of system resource like memory, network and power. To address this need in proper way, **Kohii** provides a special control flag called [MemoryMode](../../api/kohii-core/kohii.v1.core/-memory-mode/). The idea behinds `MemoryMode` is as below:
Your screen may contain many Videos at a time, and preload Videos forward so they can start as soon as possible is a legit requirement. In practice, preloading Videos consumes a lot of system resource like memory, network and power. To address this need in proper way, **Kohii** provides a special control flag called [MemoryMode](../api/kohii-core/kohii.v1.core/-memory-mode/). The idea behinds `MemoryMode` is as below:

- The idea is to allow **Kohii** to _preload around Video of interest[^1]_. When _the Video of interest_ is playing, at the same time **Kohii** will prepare the closet Videos _around_ it: the first on top, the first below, the first to the left and/or the first to the right, and the second closet Videos, etc ...

Expand Down
Expand Up @@ -2,11 +2,11 @@

_Available from v1.1.0.2011003_

<img src="../../../assets/kohii_demo_multi_player.gif" width="216" style="display: block; margin: 0 auto;"/>
<img src="../assets/kohii_demo_multi_player.gif" width="216" style="display: block; margin: 0 auto;"/>

From v1.1.0.2011003, **Kohii** adds _Playback Selector_ and _Playback Strategy_ to support multiple playbacks. The _Selector_ is a _Single Abstract Method_ that accepts a collection of _candidate_ (= the Playbacks that can play the media) and returns a collection of Playback that should play the media.

This feature is enabled at [Bucket](/customize/terms/#bucket-manager-and-group) level. Which means that: client can have multiple playbacks in a **Bucket** by using correct _Strategy_ and _Selector_. The setup is easy: you can set the _Strategy_ and _Selector_ at the time you add the **Bucket**.
This feature is enabled at [Bucket](glossary.md#bucket-manager-and-group) level. Which means that: client can have multiple playbacks in a **Bucket** by using correct _Strategy_ and _Selector_. The setup is easy: you can set the _Strategy_ and _Selector_ at the time you add the **Bucket**.

```Kotlin tab=
kohii.register(this)
Expand All @@ -29,4 +29,4 @@ The available _Strategies_ are:
- `SINGLE_PLAYER`: play the first available Playback from the list selected by the _Selector_.
- `NO_PLAYER`: do not let the _Selector_ select anything.

**NOTE**: Mutiple playbacks comes with a caveat. In Video playback, audio focus is an important aspect. The client needs to not only respect the audio focus given by system, but also to respect the audio focuses among a Video with the others in the same Application. Therefore, when the client enable `MULTI_PLAYER` _Strategy_, the library will forcefully mute the audio of all available Playbacks, regardless the number of Playbacks selected by the _Selector_. Changing to `SINGLE_PLAYER` or `NO_PLAYER` _Strategy_ will switch everything back to normal.
**NOTE**: Multiple playbacks comes with a caveat. In Video playback, audio focus is an important aspect. The client needs to not only respect the audio focus given by system, but also to respect the audio focuses among a Video with the others in the same Application. Therefore, when the client enable `MULTI_PLAYER` _Strategy_, the library will forcefully mute the audio of all available Playbacks, regardless the number of Playbacks selected by the _Selector_. Changing to `SINGLE_PLAYER` or `NO_PLAYER` _Strategy_ will switch everything back to normal.
Expand Up @@ -2,8 +2,8 @@

Until now, the setup code is always `kohii.setUp(videoUrl).bind(playerView)` which may let you think that you will need to bind the Video to a `PlayerView` instance.

In **Kohii**, target of the method `bind` is called [`container`](../../customize/terms/#renderer-and-container). While `PlayerView` is the place where Video content is rendered (and therefore it is called [`renderer`](../../customize/terms/#renderer-and-container), it can also be a `container` which _contains itself_).
In **Kohii**, target of the method `bind` is called [`container`](glossary.md#renderer-and-container). While `PlayerView` is the place where Video content is rendered (and therefore it is called [`renderer`](glossary.md#renderer-and-container), it can also be a `container` which _contains itself_).

You can bind the Video to any `ViewGroup` as container, as long as either it is a `renderer` itself, or it has no children so that it _can contain_ a `renderer` later. When you bind to a _non-renderer_ `container`, for example an empty `FrameLayout`, **Kohii** will automatically prepare and add the `PlayerView` instance to that `FrameLayout` dynamically. At the same time, the unnecessary `PlayerView` instance will be removed from `container` and put back to a `Pool`. This way, only a few `PlayerView` instances will be created and reused for as many container/Videos as possible.

By default, **Kohii** has its own logic for creating and recycling `PlayerView`, but developers can build their own by extending [**Engine**](../../api/kohii-core/kohii.v1.core/-engine) - another important component of **Kohii**. Extending **Engine** and building custom playback logic will be discussed in topics for developers.
By default, **Kohii** has its own logic for creating and recycling `PlayerView`, but developers can build their own by extending [**Engine**](../api/kohii-core/kohii.v1.core/-engine) - another important component of **Kohii**. Extending **Engine** and building custom playback logic will be discussed in topics for developers.
18 changes: 9 additions & 9 deletions docs/usage/advance.md → docs/advance-summary.md
Expand Up @@ -4,15 +4,15 @@ Advance usages session will focus on using **Kohii** with **ExoPlayer**. Using o

Here, we assume that you are familiar with **ExoPlayer**, including its core components (Player, ExoPlayer, SimpleExoPlayer, MediaSource, etc) and UI system (PlayerView, PlayerControlView, ControlDispatcher, etc).

This section may use some keywords about components in **Kohii** like **Container**, **Bucket**, etc. You can find their definitions here: [Components](../../customize/terms).
This section may use some keywords about components in **Kohii** like **Container**, **Bucket**, etc. You can find their definitions here: [Glossary](glossary.md).

Advance usages by **Kohii**:

- [Using Builder](advance/builder.md)
- [Using unique tag](advance/unique-tag.md)
- [Show/Hide thumbnail](advance/thumbnail.md)
- [Switching a Video playback between renderers](advance/switch-renderer.md)
- [Reuse PlayerView instance for multiple Videos](advance/reuse-renderer-instance.md)
- [Using MemoryMode to improve UX](advance/memory-mode.md)
- [Playing many Videos at the same time](advance/multiple-playbacks.md)
- [Manual playback](advance/manual-playback.md)
- [Using custom Kohii creators](advance-builder.md)
- [Using unique tag](advance-unique-tag.md)
- [Show/Hide thumbnail](advance-thumbnail.md)
- [Switching a Video playback between renderers](advance-switch-renderer.md)
- [Reuse PlayerView instance for multiple Videos](advance-reuse-renderer-instance.md)
- [Using MemoryMode to improve UX](advance-memory-mode.md)
- [Playing many Videos at the same time](advance-multiple-playbacks.md)
- [Manual playback](advance-manual-playback.md)
Expand Up @@ -16,6 +16,6 @@ kohii.setUp(videoUrl) {
!!! note
Note that you need to set the same unique `tag` to the Video, so that after switching to another `PlayerView`, it keeps playing smoothly, without being reset to beginning.

To help you simplify the steps, the call `bind(playerView1)` with a valid tag will return an object called [`Rebinder`](../../api/kohii-core/kohii.v1.core/-rebinder/). This `Rebinder` has one method `bind` so you can reuse this object to easily rebind a Video to any `PlayerView`. `Rebinder` is also a `Parcelable`, so you can pass this object around.
To help you simplify the steps, the call `bind(playerView1)` with a valid tag will return an object called [`Rebinder`](../api/kohii-core/kohii.v1.core/-rebinder/). This `Rebinder` has one method `bind` so you can reuse this object to easily rebind a Video to any `PlayerView`. `Rebinder` is also a `Parcelable`, so you can pass this object around.

Please check [this demo](https://github.com/eneim/kohii/tree/dev-v1/kohii-sample/src/main/java/kohii/v1/sample/ui/sview) to see how it uses `Rebinder` to switch a Video from `PlayerView` to dialog and back.
@@ -1,6 +1,6 @@
## Show/Hide thumbnail

**Kohii** provides a special interface called [`ArtworkHintListener`](../../api/kohii-core/kohii.v1.core/-playback/-artwork-hint-listener/). With this interface, **Kohii** can tell client when it should show/hide thumbnail (or _artwork_ in **Kohii**'s term). Sample code:
**Kohii** provides a special interface called [`ArtworkHintListener`](../api/kohii-core/kohii.v1.core/-playback/-artwork-hint-listener/). With this interface, **Kohii** can tell client when it should show/hide thumbnail (or _artwork_ in **Kohii**'s term). Sample code:

```Kotlin
// 1. Let ViewHolder implement ArtworkHintListener interface.
Expand All @@ -10,6 +10,7 @@ class VideoViewHolder(itemView: View): ViewHolder(itemView), ArtworkHintListener

// Override this callback to show/hide thumbnail.
override fun onArtworkHint(
playback: Playback,
shouldShow: Boolean,
position: Long,
state: Int
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions docs/css/main.css
Expand Up @@ -22,6 +22,6 @@
color: #353535;
}

html {
/* html {
font-size: 125%;
}
} */
File renamed without changes.

0 comments on commit a38d93a

Please sign in to comment.