Skip to content

Commit

Permalink
Feature/29 self signed certificate (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
GrakovNe authored Nov 12, 2024
1 parent ccfb140 commit 5b91183
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 10 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ dependencies {
implementation(libs.androidx.hilt.navigation.compose)
implementation(libs.hilt.android)
implementation(libs.androidx.media3.session)
implementation(libs.androidx.media3.datasource.okhttp)
kapt(libs.hilt.android.compiler)

implementation(libs.androidx.core.ktx)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.logging.HttpLoggingInterceptor
import org.grakovne.lissen.common.withTrustedCertificates
import org.grakovne.lissen.domain.connection.ServerRequestHeader
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
Expand All @@ -15,7 +16,9 @@ class ApiClient(
token: String? = null
) {

private val httpClient = OkHttpClient.Builder()
private val httpClient = OkHttpClient
.Builder()
.withTrustedCertificates()
.addInterceptor(
HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.NONE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.grakovne.lissen.channel.common
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.grakovne.lissen.common.withTrustedCertificates
import org.grakovne.lissen.domain.connection.ServerRequestHeader
import retrofit2.Retrofit
import java.util.concurrent.TimeUnit
Expand All @@ -13,7 +14,9 @@ class BinaryApiClient(
token: String
) {

private val httpClient = OkHttpClient.Builder()
private val httpClient = OkHttpClient
.Builder()
.withTrustedCertificates()
.addInterceptor(
HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.NONE
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.grakovne.lissen.common

import okhttp3.OkHttpClient
import java.security.KeyStore
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.TrustManagerFactory.getInstance
import javax.net.ssl.X509TrustManager

fun OkHttpClient.Builder.withTrustedCertificates(): OkHttpClient.Builder {
return try {
val trustManager = getSystemTrustManager()
val sslContext = getSystemSSLContext(trustManager)
this.sslSocketFactory(sslContext.socketFactory, trustManager)

this
} catch (ex: Exception) {
this
}
}

private fun getSystemTrustManager(): X509TrustManager {
val keyStore = KeyStore.getInstance("AndroidCAStore")
keyStore.load(null)

val trustManagerFactory = getInstance(TrustManagerFactory.getDefaultAlgorithm())
trustManagerFactory.init(keyStore)

return trustManagerFactory.trustManagers.first { it is X509TrustManager } as X509TrustManager
}

private fun getSystemSSLContext(trustManager: X509TrustManager): SSLContext {
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, arrayOf(trustManager), null)
return sslContext
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import androidx.media3.common.MediaMetadata
import androidx.media3.common.MediaMetadata.PICTURE_TYPE_FRONT_COVER
import androidx.media3.common.util.UnstableApi
import androidx.media3.datasource.DefaultDataSource
import androidx.media3.datasource.DefaultHttpDataSource
import androidx.media3.datasource.okhttp.OkHttpDataSource
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.source.ProgressiveMediaSource
import androidx.media3.session.MediaSession
Expand All @@ -22,7 +22,10 @@ import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.grakovne.lissen.channel.audiobookshelf.common.api.RequestHeadersProvider
import org.grakovne.lissen.common.withTrustedCertificates
import org.grakovne.lissen.content.LissenMediaProvider
import org.grakovne.lissen.domain.BookFile
import org.grakovne.lissen.domain.DetailedItem
Expand Down Expand Up @@ -228,19 +231,33 @@ class PlaybackService : MediaSessionService() {
progress: MediaProgress?
) = seek(chapters, progress?.currentTime)

private fun createOkHttpClient(): OkHttpClient {
return OkHttpClient
.Builder()
.withTrustedCertificates()
.addInterceptor(
HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.NONE
}
)
.build()
}

@OptIn(UnstableApi::class)
private fun buildDataSourceFactory(): DefaultDataSource.Factory {
val requestHeaders = requestHeadersProvider
.fetchRequestHeaders()
.associate { it.name to it.value }

val networkDatasourceFactory = DefaultHttpDataSource
.Factory()
val okHttpClient = createOkHttpClient()

val okHttpDataSourceFactory = OkHttpDataSource
.Factory(okHttpClient)
.setDefaultRequestProperties(requestHeaders)

return DefaultDataSource.Factory(
baseContext,
networkDatasourceFactory
okHttpDataSourceFactory
)
}

Expand Down
17 changes: 13 additions & 4 deletions app/src/main/java/org/grakovne/lissen/viewmodel/PlayerViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.grakovne.lissen.viewmodel

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
Expand Down Expand Up @@ -111,9 +112,17 @@ class PlayerViewModel @Inject constructor(
}

fun seekTo(chapterPosition: Double) {
val absolutePosition = currentChapterIndex.value
?.let { chapterIndex -> book.value?.chapters?.get(chapterIndex)?.start }
?.let { it + chapterPosition } ?: return
val currentIndex = currentChapterIndex.value ?: return

if (currentIndex < 0) {
Log.w(TAG, "Unable seek to $chapterPosition because there is no chapter")
return
}

val absolutePosition = currentIndex
.let { chapterIndex -> book.value?.chapters?.get(chapterIndex)?.start }
?.let { it + chapterPosition }
?: return

mediaRepository.seekTo(absolutePosition)
}
Expand Down Expand Up @@ -164,7 +173,7 @@ class PlayerViewModel @Inject constructor(
}

companion object {

private const val TAG = "PlayerViewModel"
private const val CURRENT_TRACK_REPLAY_THRESHOLD = 5
}
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ roomRuntime = "2.6.1"
rules = "1.6.1"
runtimeLivedata = "1.7.5"
media3Session = "1.4.1"
media3DatasourceOkhttp = "1.4.1"

[libraries]
accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanistSystemuicontroller" }
Expand Down Expand Up @@ -80,6 +81,7 @@ material3 = { module = "androidx.compose.material3:material3", version.ref = "ma
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
androidx-media3-session = { group = "androidx.media3", name = "media3-session", version.ref = "media3Session" }
androidx-media3-datasource-okhttp = { group = "androidx.media3", name = "media3-datasource-okhttp", version.ref = "media3DatasourceOkhttp" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
Expand Down

0 comments on commit 5b91183

Please sign in to comment.