Skip to content

Commit

Permalink
integrating tts with media style notification
Browse files Browse the repository at this point in the history
  • Loading branch information
kazemcodes committed Apr 6, 2022
1 parent b2909ce commit d5d03fb
Show file tree
Hide file tree
Showing 36 changed files with 1,574 additions and 1,045 deletions.
2 changes: 1 addition & 1 deletion .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />



<!-- To view extension packages in API 30+ -->
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
Expand Down Expand Up @@ -45,6 +46,7 @@
android:exported="true"
android:theme="@style/Theme.ISplash"
android:windowSoftInputMode="adjustResize">

<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand All @@ -63,6 +65,7 @@
android:host="deeplink"
android:scheme="ireader" />
</intent-filter>

</activity>
<provider
android:name="androidx.startup.InitializationProvider"
Expand All @@ -77,6 +80,9 @@
android:name="androidx.emoji2.text.EmojiCompatInitializer"
tools:node="remove" />
</provider>
<receiver
android:name="org.ireader.domain.feature_services.notification.TextReaderBroadcastReceiver"
android:exported="false" />
<!-- <provider-->
<!-- android:name="androidx.startup.InitializationProvider"-->
<!-- android:authorities="${applicationId}.androidx-startup"-->
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/java/org/ireader/infinity/di/LocalModule.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.ireader.infinity.di

import android.content.Context
import android.speech.tts.TextToSpeech
import androidx.room.Room
import dagger.Module
import dagger.Provides
Expand Down Expand Up @@ -46,6 +47,15 @@ class LocalModule {
.build()
}


@Provides
@Singleton
fun provideTextToSpeech(context: Context): TextToSpeech {
return TextToSpeech(context) {

}
}

@Provides
@Singleton
fun providesBookDao(db: AppDatabase): LibraryBookDao {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class MainActivity : ComponentActivity() {
installSplashScreen()
WindowCompat.setDecorFitsSystemWindows(window, false)
super.onCreate(savedInstanceState)

setContent {
AppTheme {
Surface(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ class PreferenceMutableState<T>(
private val state = mutableStateOf(preference.get())

init {
preference.changes()
.onEach { state.value = it }
.launchIn(scope)
try {
preference.changes()
.onEach { state.value = it }
.launchIn(scope)
} catch (e: Exception) {
}

}

override var value: T
Expand Down
10 changes: 10 additions & 0 deletions core/src/main/res/drawable/ic_baseline_fast_forward.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z" />
</vector>
10 changes: 10 additions & 0 deletions core/src/main/res/drawable/ic_baseline_fast_rewind.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z" />
</vector>
10 changes: 10 additions & 0 deletions core/src/main/res/drawable/ic_baseline_pause.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z" />
</vector>
10 changes: 10 additions & 0 deletions core/src/main/res/drawable/ic_baseline_play_arrow.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M8,5v14l11,-7z" />
</vector>
10 changes: 10 additions & 0 deletions core/src/main/res/drawable/ic_baseline_skip_next.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z" />
</vector>
10 changes: 10 additions & 0 deletions core/src/main/res/drawable/ic_baseline_skip_previous.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z" />
</vector>
3 changes: 2 additions & 1 deletion domain/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins {
id("kotlin-kapt")
id("kotlin-parcelize")
id("kotlinx-serialization")
id("dagger.hilt.android.plugin")
}

android {
Expand All @@ -23,7 +24,7 @@ dependencies {

// implementation(Deps.tachiyomi.api)
implementation(libs.tachiyomi)

implementation(androidx.media)

implementation(kotlinx.datetime)
implementation(compose.compose.activity)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,34 @@
package org.ireader.domain.feature_services.notification

import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.media.MediaMetadata
import android.media.session.PlaybackState
import android.os.Build
import android.support.v4.media.MediaMetadataCompat
import android.support.v4.media.session.MediaSessionCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.net.toUri
import androidx.work.WorkManager
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch
import org.ireader.core.R
import org.ireader.domain.models.entities.Book
import org.ireader.domain.models.entities.Chapter
import org.ireader.infinity.feature_services.flags
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton


@Singleton
class DefaultNotificationHelper @Inject constructor(
@ApplicationContext private val applicationContext: Context,
Expand Down Expand Up @@ -56,5 +74,178 @@ class DefaultNotificationHelper @Inject constructor(
applicationContext, 0, openDownloadIntent, flags
)

fun baseNotificationDownloader(
chapter: Chapter,
book: Book,
workManagerId: UUID,
): NotificationCompat.Builder {
val cancelDownloadIntent = WorkManager.getInstance(applicationContext)
.createCancelPendingIntent(workManagerId)
return NotificationCompat.Builder(applicationContext,
Notifications.CHANNEL_DOWNLOADER_PROGRESS).apply {
setContentTitle("Downloading ${book.title}")
setSmallIcon(R.drawable.ic_downloading)
setOnlyAlertOnce(true)
priority = NotificationCompat.PRIORITY_LOW
setAutoCancel(true)
setOngoing(true)
addAction(R.drawable.baseline_close_24, "Cancel", cancelDownloadIntent)
setContentIntent(openDownloadsPendingIntent)
}
}

fun updateDownloaderNotification(
chapter: Chapter,
book: Book,
workManagerId: UUID,
index: Int,
maxIndex: Int,
) {
val notification = baseNotificationDownloader(chapter, book, workManagerId).apply {
setContentText(chapter.title)
setSubText(index.toString())
setProgress(maxIndex, index, false)
}.build()

NotificationManagerCompat.from(applicationContext)
.notify(Notifications.ID_DOWNLOAD_CHAPTER_PROGRESS, notification)

}


val skipPrev = PendingIntent.getBroadcast(
applicationContext.applicationContext,
0,
Intent(applicationContext, TextReaderBroadcastReceiver::class.java).apply {
putExtra("PLAYER", 1)
},
pendingIntentFlags
)
val rewind = PendingIntent.getBroadcast(
applicationContext.applicationContext,
1,
Intent(applicationContext.applicationContext,
TextReaderBroadcastReceiver::class.java).apply {
putExtra("PLAYER", 2)
},
pendingIntentFlags
)
val pause = PendingIntent.getBroadcast(
applicationContext.applicationContext,
2,
Intent(applicationContext, TextReaderBroadcastReceiver::class.java).apply {
putExtra("PLAYER", 3)
},
pendingIntentFlags
)
val next = PendingIntent.getBroadcast(
applicationContext.applicationContext,
3,
Intent(applicationContext, TextReaderBroadcastReceiver::class.java).apply {
putExtra("PLAYER", 4)
},
pendingIntentFlags
)
val skipNext = PendingIntent.getBroadcast(
applicationContext.applicationContext,
4,
Intent(applicationContext, TextReaderBroadcastReceiver::class.java).apply {
putExtra("PLAYER", 5)
},
pendingIntentFlags
)
val cancelMediaPlater = PendingIntent.getBroadcast(
applicationContext.applicationContext,
5,
Intent(applicationContext, TextReaderBroadcastReceiver::class.java).apply {
putExtra("PLAYER", 6)
},
pendingIntentFlags
)


suspend fun basicPlayingTextReaderNotification(
chapter: Chapter,
book: Book,
playing: Boolean,
progress: Int,
mediaSessionCompat: MediaSessionCompat,
): NotificationCompat.Builder {
mediaSessionCompat.apply {
isActive = true
setMetadata(MediaMetadataCompat.Builder().apply {
putText(MediaMetadata.METADATA_KEY_TITLE, chapter.title)
}.build())
val actions =
PlaybackState.ACTION_PLAY_PAUSE or PlaybackState.ACTION_STOP or PlaybackState.ACTION_SKIP_TO_NEXT or PlaybackState.ACTION_SKIP_TO_PREVIOUS

}
return NotificationCompat.Builder(applicationContext,
Notifications.CHANNEL_TEXT_READER_PROGRESS).apply {
setContentTitle(chapter.title)
setContentText("${progress}/${chapter.content.size}")
setSmallIcon(org.ireader.core.R.drawable.ic_infinity)
setOnlyAlertOnce(true)
// setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
setLargeIcon(applicationContext, book.cover)
//setShowWhen(false)
priority = NotificationCompat.PRIORITY_LOW

addAction(R.drawable.ic_baseline_skip_previous,
"Previous Chapter",
skipPrev)
addAction(
R.drawable.ic_baseline_fast_rewind,
"Previous Paragraph",
rewind)

if (playing) {
addAction(R.drawable.ic_baseline_pause, "Pause", pause)
} else {
addAction(R.drawable.ic_baseline_play_arrow, "Start", pause)

}
addAction(R.drawable.ic_baseline_fast_forward, "Next Paragraph", next)
addAction(R.drawable.ic_baseline_skip_next, "Next Chapter", skipNext)
setStyle(androidx.media.app.NotificationCompat.MediaStyle()
.setCancelButtonIntent(cancelMediaPlater)
.setMediaSession(mediaSessionCompat.sessionToken)
.setShowActionsInCompactView(1, 2, 3)
)
setSubText(book.title)
color = applicationContext.resources.getColor(R.color.blue_200)

//setColorized(true)
//setAutoCancel(true)
setOngoing(false)
}


}
}

@AndroidEntryPoint()
class TextReaderBroadcastReceiver : BroadcastReceiver() {

@Inject
lateinit var state: NotificationStates

val scope = CoroutineScope(Dispatchers.Main.immediate + SupervisorJob())

override fun onReceive(p0: Context?, intent: Intent?) {
intent?.getIntExtra("PLAYER", -1)?.let {
scope.launch {
state.mediaPlayerNotification.emit(it)
}
}


}

}

@Singleton
class NotificationStates @Inject constructor() {
val mediaPlayerNotification = MutableSharedFlow<Int>()
}

}
Loading

0 comments on commit d5d03fb

Please sign in to comment.