Skip to content

Commit 6569e57

Browse files
session timer added
1 parent c5294bf commit 6569e57

File tree

8 files changed

+449
-20
lines changed

8 files changed

+449
-20
lines changed

Diff for: app/src/main/AndroidManifest.xml

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:tools="http://schemas.android.com/tools">
44

5+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
6+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
7+
58
<application
69
android:name=".StudySmartApp"
710
android:allowBackup="true"
@@ -24,6 +27,9 @@
2427
<category android:name="android.intent.category.LAUNCHER" />
2528
</intent-filter>
2629
</activity>
30+
<service
31+
android:name=".presentation.session.StudySessionTimerService"
32+
android:exported="false" />
2733
</application>
2834

2935
</manifest>

Diff for: app/src/main/java/com/example/studysmart/MainActivity.kt

+61-2
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,85 @@
11
package com.example.studysmart
22

3+
import android.content.ComponentName
4+
import android.content.Context
5+
import android.content.Intent
6+
import android.content.ServiceConnection
7+
import android.os.Build
38
import android.os.Bundle
9+
import android.os.IBinder
410
import androidx.activity.ComponentActivity
511
import androidx.activity.compose.setContent
12+
import androidx.compose.runtime.getValue
13+
import androidx.compose.runtime.mutableStateOf
14+
import androidx.compose.runtime.setValue
615
import androidx.compose.ui.graphics.toArgb
16+
import androidx.core.app.ActivityCompat
717
import com.example.studysmart.domain.model.Session
818
import com.example.studysmart.domain.model.Subject
919
import com.example.studysmart.domain.model.Task
1020
import com.example.studysmart.presentation.NavGraphs
21+
import com.example.studysmart.presentation.destinations.SessionScreenRouteDestination
22+
import com.example.studysmart.presentation.session.StudySessionTimerService
1123
import com.example.studysmart.presentation.theme.StudySmartTheme
1224
import com.ramcosta.composedestinations.DestinationsNavHost
25+
import com.ramcosta.composedestinations.navigation.dependency
1326
import dagger.hilt.android.AndroidEntryPoint
1427

1528
@AndroidEntryPoint
1629
class MainActivity : ComponentActivity() {
30+
31+
private var isBound by mutableStateOf(false)
32+
private lateinit var timerService: StudySessionTimerService
33+
private val connection = object : ServiceConnection {
34+
override fun onServiceConnected(p0: ComponentName?, service: IBinder?) {
35+
val binder = service as StudySessionTimerService.StudySessionTimerBinder
36+
timerService = binder.getService()
37+
isBound = true
38+
}
39+
40+
override fun onServiceDisconnected(p0: ComponentName?) {
41+
isBound = false
42+
}
43+
}
44+
45+
override fun onStart() {
46+
super.onStart()
47+
Intent(this, StudySessionTimerService::class.java).also { intent ->
48+
bindService(intent, connection, Context.BIND_AUTO_CREATE)
49+
}
50+
}
51+
1752
override fun onCreate(savedInstanceState: Bundle?) {
1853
super.onCreate(savedInstanceState)
1954
setContent {
20-
StudySmartTheme {
21-
DestinationsNavHost(navGraph = NavGraphs.root)
55+
if (isBound) {
56+
StudySmartTheme {
57+
DestinationsNavHost(
58+
navGraph = NavGraphs.root,
59+
dependenciesContainerBuilder = {
60+
dependency(SessionScreenRouteDestination) { timerService }
61+
}
62+
)
63+
}
2264
}
2365
}
66+
requestPermission()
67+
}
68+
69+
private fun requestPermission() {
70+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
71+
ActivityCompat.requestPermissions(
72+
this,
73+
arrayOf(android.Manifest.permission.POST_NOTIFICATIONS),
74+
0
75+
)
76+
}
77+
}
78+
79+
override fun onStop() {
80+
super.onStop()
81+
unbindService(connection)
82+
isBound = false
2483
}
2584
}
2685

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.example.studysmart.di
2+
3+
import android.app.NotificationManager
4+
import android.content.Context
5+
import androidx.core.app.NotificationCompat
6+
import com.example.studysmart.R
7+
import com.example.studysmart.presentation.session.ServiceHelper
8+
import com.example.studysmart.util.Constants.NOTIFICATION_CHANNEL_ID
9+
import dagger.Module
10+
import dagger.Provides
11+
import dagger.hilt.InstallIn
12+
import dagger.hilt.android.components.ServiceComponent
13+
import dagger.hilt.android.qualifiers.ApplicationContext
14+
import dagger.hilt.android.scopes.ServiceScoped
15+
16+
@Module
17+
@InstallIn(ServiceComponent::class)
18+
object NotificationModule {
19+
20+
@ServiceScoped
21+
@Provides
22+
fun provideNotificationBuilder(
23+
@ApplicationContext context: Context
24+
): NotificationCompat.Builder {
25+
return NotificationCompat
26+
.Builder(context, NOTIFICATION_CHANNEL_ID)
27+
.setContentTitle("Study Session")
28+
.setContentText("00:00:00")
29+
.setSmallIcon(R.drawable.ic_launcher_foreground)
30+
.setOngoing(true)
31+
.setContentIntent(ServiceHelper.clickPendingIntent(context))
32+
}
33+
34+
@ServiceScoped
35+
@Provides
36+
fun provideNotificationManager(
37+
@ApplicationContext context: Context
38+
): NotificationManager {
39+
return context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.example.studysmart.presentation.session
2+
3+
import android.app.PendingIntent
4+
import android.app.TaskStackBuilder
5+
import android.content.Context
6+
import android.content.Intent
7+
import androidx.core.net.toUri
8+
import com.example.studysmart.MainActivity
9+
import com.example.studysmart.util.Constants.CLICK_REQUEST_CODE
10+
11+
object ServiceHelper {
12+
13+
fun clickPendingIntent(context: Context): PendingIntent {
14+
val deepLinkIntent = Intent(
15+
Intent.ACTION_VIEW,
16+
"study_smart://dashboard/session".toUri(),
17+
context,
18+
MainActivity::class.java
19+
)
20+
return TaskStackBuilder.create(context).run {
21+
addNextIntentWithParentStack(deepLinkIntent)
22+
getPendingIntent(
23+
CLICK_REQUEST_CODE,
24+
PendingIntent.FLAG_IMMUTABLE
25+
)
26+
}
27+
}
28+
29+
fun triggerForegroundService(context: Context, action: String) {
30+
Intent(context, StudySessionTimerService::class.java).apply {
31+
this.action = action
32+
context.startService(this)
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)