jellyfin / jellyfin-sdk-kotlin Goto Github PK
View Code? Open in Web Editor NEWKotlin SDK for Jellyfin, supporting Android and JVM targets
Home Page: https://kotlin-sdk.jellyfin.org
License: GNU Lesser General Public License v3.0
Kotlin SDK for Jellyfin, supporting Android and JVM targets
Home Page: https://kotlin-sdk.jellyfin.org
License: GNU Lesser General Public License v3.0
The GH actions workflow that creates the OpenAPI schema update pull requests should automatically add "enhancement" labels to the pull requests so it doesn't need to be done manually. Example PR #603.
Unfortunately JCenter is closing in a few months. We need to publish the apiclient somewhere else before this happens. Additionally all our Java based projects (the Android apps) need to switch to different repositories for all dependencies.
I think our best bet is to wait a bit and see what other projects in the java ecosystem do before we act.
See the jfrog blog article for some more information:
https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/
Unfortunately not everything worked in the 0.7.1 release. The assets were not uploaded. Not a major issue but it should be fixed for the next release.
In case the Azure logs get too old and will be deleted.
2020-08-18T15:58:47.2723873Z ##[section]Starting: GitHub Upload
2020-08-18T15:58:47.2738850Z ==============================================================================
2020-08-18T15:58:47.2739452Z Task : GitHub Release
2020-08-18T15:58:47.2739881Z Description : Create, edit, or delete a GitHub release
2020-08-18T15:58:47.2740288Z Version : 0.160.5
2020-08-18T15:58:47.2740640Z Author : Microsoft Corporation
2020-08-18T15:58:47.2741691Z Help : https://aka.ms/AA5vv5o
2020-08-18T15:58:47.2742474Z ==============================================================================
2020-08-18T15:58:47.4668852Z 9bde9970-f931-4741-b0e3-f9f2bbcbf4ae exists true
2020-08-18T15:58:47.5062106Z Computing changes made in this release...
2020-08-18T15:58:47.7352006Z Fetching the latest published release...
2020-08-18T15:58:47.9899384Z Found the latest published release: https://github.com/jellyfin/jellyfin-apiclient-java/releases/tag/v0.7.1
2020-08-18T15:58:48.2483200Z Fetching the list of commits since the last published release...
2020-08-18T15:58:48.5968714Z No changes were found. The provided target commit is the same as the commit of the last published release.
2020-08-18T15:58:48.5972148Z Release notes file: /home/vsts/work/1/s is a directory and not a file.
2020-08-18T15:58:48.5973273Z Fetching the release for tag: v0.7.1
2020-08-18T15:58:48.9265051Z Found a release for tag: v0.7.1
2020-08-18T15:58:48.9272950Z Editing the release with tag: v0.7.1
2020-08-18T15:58:49.2010463Z Uploading assets...
2020-08-18T15:58:49.2016049Z Searching for file(s) matching '**/distributions/*-${JELLYFIN_VERSION}.zip'.
2020-08-18T15:58:49.3337046Z No files found matching '**/distributions/*-${JELLYFIN_VERSION}.zip'. Nothing to upload.
2020-08-18T15:58:49.3338629Z Searching for file(s) matching '**/libs/*-${JELLYFIN_VERSION}.jar'.
2020-08-18T15:58:49.4329634Z No files found matching '**/libs/*-${JELLYFIN_VERSION}.jar'. Nothing to upload.
2020-08-18T15:58:49.4331135Z Searching for file(s) matching '**/libs/*-${JELLYFIN_VERSION}-sources.jar'.
2020-08-18T15:58:49.5278786Z No files found matching '**/libs/*-${JELLYFIN_VERSION}-sources.jar'. Nothing to upload.
2020-08-18T15:58:49.5280259Z All assets uploaded successfully.
2020-08-18T15:58:49.5281914Z Release edited successfully https://github.com/jellyfin/jellyfin-apiclient-java/releases/tag/v0.7.1
2020-08-18T15:58:49.5322867Z ##[section]Finishing: GitHub Upload
2020-08-19T07:33:23.5116508Z ##[section]Starting: GitHub Upload
2020-08-19T07:33:23.5129081Z ==============================================================================
2020-08-19T07:33:23.5129845Z Task : GitHub Release
2020-08-19T07:33:23.5130467Z Description : Create, edit, or delete a GitHub release
2020-08-19T07:33:23.5130888Z Version : 0.160.5
2020-08-19T07:33:23.5131588Z Author : Microsoft Corporation
2020-08-19T07:33:23.5132025Z Help : https://aka.ms/AA5vv5o
2020-08-19T07:33:23.5133224Z ==============================================================================
2020-08-19T07:33:23.7313368Z 9bde9970-f931-4741-b0e3-f9f2bbcbf4ae exists true
2020-08-19T07:33:23.7802548Z Computing changes made in this release...
2020-08-19T07:33:23.9567074Z Fetching the latest published release...
2020-08-19T07:33:24.1384291Z Found the latest published release: https://github.com/jellyfin/jellyfin-apiclient-java/releases/tag/v0.7.2
2020-08-19T07:33:24.3440201Z Fetching the list of commits since the last published release...
2020-08-19T07:33:24.6088660Z No changes were found. The provided target commit is the same as the commit of the last published release.
2020-08-19T07:33:24.6091549Z Release notes file: /home/vsts/work/1/s is a directory and not a file.
2020-08-19T07:33:24.6101088Z Fetching the release for tag: v0.7.2
2020-08-19T07:33:24.8060860Z Found a release for tag: v0.7.2
2020-08-19T07:33:24.8061699Z Editing the release with tag: v0.7.2
2020-08-19T07:33:25.0480932Z Uploading assets...
2020-08-19T07:33:25.0488543Z Searching for file(s) matching '/home/vsts/work/1/s/**/distributions/*-${JELLYFIN_VERSION}.zip'.
2020-08-19T07:33:25.1717647Z No files found matching '/home/vsts/work/1/s/**/distributions/*-${JELLYFIN_VERSION}.zip'. Nothing to upload.
2020-08-19T07:33:25.1719290Z Searching for file(s) matching '/home/vsts/work/1/s/**/libs/*-${JELLYFIN_VERSION}.jar'.
2020-08-19T07:33:25.2674781Z No files found matching '/home/vsts/work/1/s/**/libs/*-${JELLYFIN_VERSION}.jar'. Nothing to upload.
2020-08-19T07:33:25.2675919Z Searching for file(s) matching '/home/vsts/work/1/s/**/libs/*-${JELLYFIN_VERSION}-sources.jar'.
2020-08-19T07:33:25.3548400Z No files found matching '/home/vsts/work/1/s/**/libs/*-${JELLYFIN_VERSION}-sources.jar'. Nothing to upload.
2020-08-19T07:33:25.3549354Z All assets uploaded successfully.
2020-08-19T07:33:25.3550407Z Release edited successfully https://github.com/jellyfin/jellyfin-apiclient-java/releases/tag/v0.7.2
2020-08-19T07:33:25.3588737Z ##[section]Finishing: GitHub Upload
a function that takes the list of candidate server addresses and returns which one is valid
It would be nice to have a function that extends the functionality of the function that will "normalize" a server string and return a list of candidates by connecting to the servers in the list and returning the "best". The best server will always prefer https over http but otherwise returns the first in the list that responds to a public system info.
Its been a while I am trying to create a Jellyfin Android Client for a sideproject. Made log-in work, but fetching media and playing it seems a lot harder. Not in a technical way but in a API way...
At first I started from here https://api.jellyfin.org which is just a reference, it has almost no explanation. So how do I know what is what?
For example, what is difference between Libraries
and UserLibraries
? how to get the list of media, movies, download links?
I have been debuging Findroid for a while and it is a pain. On their app it just works and on mine it throws exceptions...
First of all thank you so much for making this library, it allowed me to create Findroid ๐
While looking at the permissions I saw that READ_EXTERNAL_STORAGE is requested.
But is this really required? I removed it from the manifest and everything still seems to work.
According to the docs this is only required when you want to read all contents from external storage and I don't think this library does that. But maybe I'm wrong.
https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE
Pull requests that change files in any of the kotlin-generated
directories or the generator module should trigger a GitHub workflow that runs the generator and validates the sources in the pull request match. If a difference is found it should fail the task.
This will help testing the integrity of "Update OpenAPI spec" merge requests.
It's sometimes unclear where to find more info about a class or field using https://api.jellyfin.org or https://jellyfin.org/docs/plugin-api or by googling.
Is it possible for the generator to automatically add a url in the source as a comment?
example:
/*
** https://jellyfin.org/docs/plugin-api/MediaBrowser.Model.Dto.MediaSourceInfo.html
*/
public class MediaSourceInfo
{
...
afaik the generator doesn't use the plugin-api, but I used it in this example since I can't find MediaSourceInfo on api.jellyfin.org
I am new to Jellyfin and while playing around I saw the send message feature for messaging active sessions. I tried it and found that I am not seeing messages on my android. I am able to send messages from it, but not receive. No errors show on either side, it just never pops up anywhere.
The next Jellyfin version, 10.7, adds new properties that are not-null. Because of this those types are not-null in the apiclient too. This will cause issues with JSON deserialization when using the apiclient with 10.6<=.
Example:
A new property in PublicSystemInfo, StartupWizardCompleted (boolean, not null) was added. If we now use getPublicSystemInfo
in SystemApi
it will fail for servers not emitting that field because we can't set it to a default value.
Getting this error, using the latest Jellyfin version (10.8.5) and the latest sdk version (1.3.6).
Seems like it expects TranscodeReasons to be a String?
kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 5217: Expected beginning of the string, but got [ at path: $[0].TranscodingInfo.TranscodeReasons
JSON input: .....hannels":6,"TranscodeReasons":["ContainerBitrateExceedsLimit.....
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24) ~[bundleFile:?]
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32) ~[bundleFile:?]
at kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:528) ~[bundleFile:?]
We already add Dokka documentation to the artifacts on Maven Central (docs are required). It would be nice to publish them somewhere more accessible. Something like developers.jellyfin.org/sdk-kotlin/1.0.0/
.
When a user is dumb and makes a typo and the HTTP port is out of range the discovery stuff throws an exception and the Android TV app crashes... I was the dumb user.
Stack Trace:
java.lang.IllegalArgumentException: port must be between 0 and 65535, or 0 if not set
at io.ktor.http.Url.<init>(URLBuilder.kt:144)
at io.ktor.http.URLBuilder.build(URLBuilder.kt:98)
at org.jellyfin.sdk.discovery.AddressCandidateHelper.<init>(AddressCandidateHelper.kt:55)
at org.jellyfin.sdk.discovery.DiscoveryService.getAddressCandidates(DiscoveryService.kt:27)
at org.jellyfin.androidtv.auth.repository.ServerRepositoryImpl$addServer$1.invokeSuspend(ServerRepository.kt:90)
at org.jellyfin.androidtv.auth.repository.ServerRepositoryImpl$addServer$1.invoke(Unknown Source:8)
at org.jellyfin.androidtv.auth.repository.ServerRepositoryImpl$addServer$1.invoke(Unknown Source:4)
at kotlinx.coroutines.flow.SafeFlow.collectSafely(Builders.kt:61)
at kotlinx.coroutines.flow.AbstractFlow.collect(Flow.kt:230)
at org.jellyfin.androidtv.ui.startup.ServerAddViewModel$addServer$1.invokeSuspend(ServerAddViewModel.kt:19)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:367)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
at org.jellyfin.androidtv.ui.startup.ServerAddViewModel.addServer(ServerAddViewModel.kt:18)
at org.jellyfin.androidtv.ui.startup.fragment.ServerAddFragment.submitAddress(ServerAddFragment.kt:107)
at org.jellyfin.androidtv.ui.startup.fragment.ServerAddFragment.onCreateView$lambda-4$lambda-3(ServerAddFragment.kt:50)
at org.jellyfin.androidtv.ui.startup.fragment.ServerAddFragment.$r8$lambda$uSCCu62gCVZN90XjWAl5IwN7O5U(Unknown Source:0)
at org.jellyfin.androidtv.ui.startup.fragment.ServerAddFragment$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access$3100(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@9106673, Dispatchers.Main.immediate]
Log lines before exception:
08-13 07:35:18.707 D/ServerRepositoryImpl$addServer( 4635): Adding server http://192.168.1.10:80961
08-13 07:35:18.707 D/AddressCandidateHelper( 4635): Input is http://192.168.1.10:80961
Regression from #446, SSL errors are not caught. Ideally we should wrap them in a subclass of ApiClientException. This issue only happens for badly configured servers.
Stacktrace from jellyfin/jellyfin-androidtv#1920.
javax.net.ssl.SSLHandshakeException: Handshake failed
at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:286)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@b5b80bf, Dispatchers.Main.immediate]
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x941ce4c8: Failure in SSL library, usually a protocol error
error:100000f7:SSL routines:OPENSSL_internal:WRONG_VERSION_NUMBER (external/boringssl/src/ssl/tls_record.cc:242 0xa33aef0b:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.NativeSsl.doHandshake(NativeSsl.java:375)
at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:224)
... 20 more
Hi, wanted to try this library and also added Robolectric.
Anyways this line returns null and the test crashes
Is Robolectric supported? anyways my usecase is that I can play around with jellyfin-sdk-kotlin
faster than with debugging/starting random Activities with random buttons. I could try with Instrumentation test, but idk... I dont like those
Moving the structure of the library to Kotlin Mutliplatform allows us to add the Android specific code to the core library. This would make it easier to use the library as users don't need to include the Android platform separately. It also makes it easier for us to support different platforms like JavaScript, WASM, Native or iOS in the future.
I already tested this in #187 and it might be a relatively easy change.
Describe the bug
I am setting the timeout to 60 seconds in the following manner:
private const val HTTP_CLIENT_TIMEOUT_IN_MS = 60000L
@Singleton
@Provides
internal fun providesKtorClient(jellyfin: Jellyfin): KtorClient {
val clientOptions = HttpClientOptions(followRedirects = true, timeout = HTTP_CLIENT_TIMEOUT_IN_MS)
return jellyfin.createApi(baseUrl = null, httpClientOptions = clientOptions)
}
However I have noticed that some requests time out after 6-10 seconds rather than 60 seconds.
Actual result
This is what the timeout log looks like:
Socket timeout has expired [url=https://somedummyurl.com/Users/a8888-cca3-4c0c-8668-a05fd9cb0b9f/Items/Latest?limit=10&groupItems=true, socket_timeout=unknown] ms
Notice the socket_timeout is unknown.
Expected result
Request will time out after custom timeout period (60 seconds in this case).
The current Gradle setup includes the Android linter (automatically added for Android projects) and Detekt (manually added) for linting. Right now both are unused in the GitHub actions.
I'd like to automatically lint the codebase on pull requests and report any new issues using annotations or in a comment. My previous attempt (#163) didn't work out like I wanted so I'll need to rethink how to approach this issue.
Although we do use the ApiClient interface in most places it doesn't include the request, get, post and delete functions. This is because we use inline functions with reified types, which are not supported when using interfaces. Preferably we'd fix this by passing the class as parameters instead of using generics but when I looked into this it didn't look like a possibility.
Separating the KtorClient (implementation) from the ApiClient (interface) it would allow the usage of custom HTTP clients and make it easier to change it if we decide to drop Ktor at some point.
It looks like the EndBug/[email protected]
action doesn't work as I expected. It doesn't force-push the changes properly because it checks out the remote branch. Might need to use another action or write an simple bash script for it.
When a new Jellyfin server version is released the OpenAPI specification is published at https://repo.jellyfin.org/releases/openapi/. Right now updating the SDK requires running the updateApiSpecStable
gradle task to download the JSON file and run the generator to create the generated sources.
It would be amazing if we could automate this process by creating a workflow that runs every day/week/? and compares the latest stable specification with the one in the repository. If any changes are found it should update the generated sources, push it to a new branch and create a pull request. We can then validate this PR manually to see if everything works correctly, and make changes to it if required.
white background
+ white text
= invisible
๐คฏ
Sometimes people use a baseurl and only have a redirect on the index page (e.g. jellyfin.local -> jellyfin.local/jellyfin). We should support these redirects to allow easier setup in Jellyfin clients.
I try to use ItemUpdateApi#updateItem(itemId: UUID, data
: BaseItemDto)
but an error occurred
{
"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title":"One or more validation errors occurred.",
"status":400,
"traceId":"00-33dd05cfdb47ed4088bf0ae90b8b86da-8b9f9586acc83544-00",
"errors":{
"request":[
"The request field is required."
],
"$.DateCreated":[
"The JSON value could not be converted to System.DateTime. Path: $ | LineNumber: 0 | BytePositionInLine: 52. Path: $.DateCreated | LineNumber: 0 | BytePositionInLine: 268."
]
}
}
Server:
https://github.com/jellyfin/jellyfin/blob/master/MediaBrowser.Model/Session/TranscodingInfo.cs#L32
OpenAPI:
"TranscodeReasons": {
"enum": [
"ContainerNotSupported",
"VideoCodecNotSupported",
"AudioCodecNotSupported",
"SubtitleCodecNotSupported",
"AudioIsExternal",
"SecondaryAudioNotSupported",
"VideoProfileNotSupported",
"VideoLevelNotSupported",
"VideoResolutionNotSupported",
"VideoBitDepthNotSupported",
"VideoFramerateNotSupported",
"RefFramesNotSupported",
"AnamorphicVideoNotSupported",
"InterlacedVideoNotSupported",
"AudioChannelsNotSupported",
"AudioProfileNotSupported",
"AudioSampleRateNotSupported",
"AudioBitDepthNotSupported",
"ContainerBitrateExceedsLimit",
"VideoBitrateNotSupported",
"AudioBitrateNotSupported",
"UnknownVideoStreamInfo",
"UnknownAudioStreamInfo",
"DirectPlayError",
"VideoRangeTypeNotSupported"
],
"type": "string"
}
Generated:
@SerialName("TranscodeReasons")
public val transcodeReasons: String,
Expected generated:
@SerialName("TranscodeReasons")
public val transcodeReasons: Collection<TranscodeReason>,
It is not flexible to custom HttpClientConfig for now
Is it possible to support a way add more feature like log?
Jellyfin on android and from the Fdroid store is constantly restarting itself. I force quit it and it just restarts itself some time later.
When #54 is merged we can publish the apiclient to Bintray which is nice. What would be really nice however is this process being automated.
We should add a new task to the Azure pipeline that will run the publishDefaultPublicationToBintrayRepository
Gradle job with the environment variables specified in #54 set. This way we can automagically publish to Bintray.
Another thing that we could probably do (however, I did not test it) is publishing the master branch with the version set as SNAPSHOT
.
Some endpoints have a lot of (query-)parameters. Sometimes the values of these parameters change based on some logic. Right now you'll need to write separate function calls or create variables to later pass to the operation function.
A solution for this annoyance would be to add data classes that can be used instead of a big parameter list. They would be an addition to the existing functions, not replace them.
A (simple) example for the "getAudioStreamUrl" operation in the audio api:
// Before
val streamUrl = api.audioApi.getAudioStreamUrl(
itemId = itemId,
mediaSourceId = mediaSource.id,
deviceId = api.deviceInfo.id,
)
// After
var audioStreamRequest = GetAudioStreamRequest(
itemId = itemId,
mediaSourceId = mediaSource.id,
deviceId = api.deviceInfo.id,
)
// Imagine a lot of logic here instead of just this single line
if (someOtherMediaSourceId != null) audioStreamRequest = audioStreamRequest.copy(mediaSourceId = someOtherMediaSourceId)
val streamUrl = api.audioApi.getAudioStreamUrl(audioStreamRequest)
The requests should be the exact same as the request parameters but in a data class instead of function parameters.
10.8 added support for authentication via headers in websockets
We've had a discussion about renaming this project before. A few names came up like "jellyfin-sdk-kotlin" and "jellyfin-apiclient-kotlin".
Since the project is entirely written in Kotlin now I think it's better to not use the term "java" in the name. I'd like to start using Kotlin Multiplatform at some point which allows us to target not only the JVM but also JavaScript, WebAssembly and iOS (just to name a few).
I'd rather rename the repository before releasing 1.0.0, although this only matters for the metadata because our package and group use "org.jellyfin.apiclient".
The new readme in #193 already uses the new name ๐
edit (2021-03-19): the initial plan (written above) was to rename to "apiclient" but we decided "sdk" makes more sense. See my comment below for the new plan.
I'm following up on an issue I described in jellyfin/jellyfin-android#949 (comment). I've an HTTP redirect set from a custom domain to the Jellyfin server. Works great on browsers with both HTTP and HTTPS, even on LG webos app. The android client, however, refuses to follow the redirect URL and instead lists the tried candidates:
Tried 5 candidates for input, without success.
Unable to reach server:
- https://subdomain.domain.com
- https://subdomain.domain.com:8096
- https://subdomain.domain.com:8920
- http://subdomain.domain.com
- http://subdomain.domain.com:8096
Could it be possible to allow redirected URLs (301/302) to be acceptable as server URLs instead of outright rejecting them? I believe it could be fixed by adjusting the acceptable response code here: https://github.com/jellyfin/jellyfin-sdk-kotlin/blob/master/jellyfin-core/src/commonMain/kotlin/org/jellyfin/sdk/discovery/RecommendedServerDiscovery.kt#L125.
We're using Duration in most places so doing it in HttpClientOptions makes sense. Also helps to prevent issues because you can say 30.seconds
instead of 30_000 // seconds
Right now when a connection fails the SDK doesn't attempt to reconnect. We should implement some smart reconnect behavior that will attempt to reconnect automatically.
null
or empty lists.
The generator should read x-jellyfin-version
from the openapi document and put it somewhere in the code so we always know the "api version".
Especially on mobile devices the network can sometimes drop or have other issues. It would be nice if the SDK could automatically retry network requests when a network issue occurs. We need to make sure a retry is not attempted when only the response fails. The server could have mutated something already and retrying could cause issues. (I think this is also true for GET requests).
The behavior for retrying should be configurable in the HttpClientOptions.
The new API generated from the OpenAPI spec does not contain the WebSocket logic. This needs to be added manually to replace the current WebSockets. Ideally using Ktor.
An upcoming server update (probably 10.8) will change the format from Major.Minor.Build.Revision
to Major.Minor.Build
(10.7.0.0 -> 10.7.0). We need to validate if the generator and core library keep behaving as we expect. It's probably fine though.
Reference: jellyfin/jellyfin#5661
Hi,
I'm trying to use a local edited copy of the SDK for testing purposes. But when I changed the sdk.version in the gradle.properties from "default" to "local" in jellyfin-android, then include the SDK output library that was created, jellyfin-sdk-kotlin\jellyfin-platform-android\build\outputs\aar\jellyfin-platform-android-debug.aar, I was getting this error when debugging jellyfin-android:
Execution failed for task ':app:dataBindingMergeDependencyArtifactsProprietaryDebug'.
> Could not resolve all files for configuration ':app:proprietaryDebugCompileClasspath'.
> Could not find org.jellyfin.sdk:jellyfin-platform-android:latest-SNAPSHOT.
Required by:
project :app
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
I'm lost at the possible solution provided. Pardon my ignorance but how do I include a local copy of jellyfin SDK for testing in jellyfin-android? Thank you in advance.
https://kotlinlang.org/docs/reference/whatsnew14.html#explicit-api-mode-for-library-authors
All public modules (jellyfin-xx, not samples/generator) should use explicitApi()
.
Right now connection issues are emitted as MissingSystemInfo, with the throwable pointing to an ApiClientException with a cause containing the actual exception emitted from OkHttp.
This can be made better/easier.
I'd suggest creating a new issue type "NoConnection". It should contain the throwable and an enum explaining what went wrong with the connection: bad SSL, no internet etc.
Right now we set the defaultValue to null
when a property is nullable. But the openapi document contains a few properties of type boolean or integer with defaults. We should use these defaults.
When a property has both a default value and nullability we should prefer the default value above the default null value.
Any functionality dealing with Emby Connect should be removed.
When UserApi.authenticateUserByName
is called on API 23 then it crashes with
W/System.err: java.lang.NoClassDefFoundError: Failed resolution of: Ljava/time/ZoneId;
W/System.err: at org.jellyfin.sdk.model.serializer.DateTimeSerializer.<init>(DateTimeSerializer.kt:16)
W/System.err: at org.jellyfin.sdk.model.api.UserDto$$serializer.deserialize(UserDto.kt:27)
W/System.err: at org.jellyfin.sdk.model.api.UserDto$$serializer.deserialize(UserDto.kt:27)
W/System.err: at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59)
W/System.err: at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:38)
W/System.err: at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
W/System.err: at kotlinx.serialization.encoding.AbstractDecoder.decodeNullableSerializableElement(AbstractDecoder.kt:79)
W/System.err: at org.jellyfin.sdk.model.api.AuthenticationResult$$serializer.deserialize(AuthenticationResult.kt:12)
W/System.err: at org.jellyfin.sdk.model.api.AuthenticationResult$$serializer.deserialize(AuthenticationResult.kt:12)
W/System.err: at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59)
W/System.err: at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:38)
W/System.err: at kotlinx.serialization.json.Json.decodeFromString(Json.kt:100)
W/System.err: at org.jellyfin.sdk.api.operations.UserApi.authenticateUserByName(UserApi.kt:299)
W/System.err: at org.jellyfin.sdk.api.operations.UserApi$authenticateUserByName$1.invokeSuspend(UserApi.kt)
W/System.err: at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:191)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:147)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:15)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:93)
W/System.err: at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:191)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:147)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:15)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:93)
W/System.err: at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:191)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:147)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:15)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:93)
W/System.err: at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:191)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:147)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:15)
W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:93)
W/System.err: at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
W/System.err: at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
W/System.err: at android.os.Handler.handleCallback(Handler.java:739)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err: at android.os.Looper.loop(Looper.java:148)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5417)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
W/System.err: Caused by: java.lang.ClassNotFoundException: Didn't find class "java.time.ZoneId" on path: DexPathList[[zip file "/data/app/com.shalva97.jellylist.debug-2/base.apk"],nativeLibraryDirectories=[/data/app/com.shalva97.jellylist.debug-2/lib/x86_64, /vendor/lib64, /system/lib64]]
W/System.err: at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
W/System.err: at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
W/System.err: at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
W/System.err: ... 43 more
W/System.err: Suppressed: java.lang.ClassNotFoundException: java.time.ZoneId
W/System.err: at java.lang.Class.classForName(Native Method)
W/System.err: at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
W/System.err: at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
W/System.err: at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
W/System.err: ... 44 more
W/System.err: Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
This should be published to JCenter (or similar) so it can be included as a maven or gradle dependency.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.