Skip to content

Commit

Permalink
updated new version
Browse files Browse the repository at this point in the history
- fix autostart
- better flip detection
  • Loading branch information
robinsrk committed Dec 30, 2024
1 parent a586987 commit 728f4e4
Show file tree
Hide file tree
Showing 15 changed files with 339 additions and 264 deletions.
1 change: 1 addition & 0 deletions .idea/.name

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

6 changes: 6 additions & 0 deletions .idea/AndroidProjectSystem.xml

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

26 changes: 26 additions & 0 deletions .idea/appInsightsSettings.xml

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

6 changes: 6 additions & 0 deletions .idea/compiler.xml

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

2 changes: 1 addition & 1 deletion .idea/kotlinc.xml

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

3 changes: 1 addition & 2 deletions .idea/misc.xml

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

6 changes: 6 additions & 0 deletions .idea/vcs.xml

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

4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ android {
applicationId = "dev.robin.flip_2_dnd"
minSdk = 23
targetSdk = 34
versionCode = 7
versionName = "1.0.7"
versionCode = 8
versionName = "1.0.8"
vectorDrawables {
useSupportLibrary = true
}
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
<uses-feature android:name="android.hardware.sensor.gyroscope" android:required="true" />
Expand Down Expand Up @@ -40,5 +41,12 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".services.AutoStartService"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
192 changes: 96 additions & 96 deletions app/src/main/java/dev/robin/flip_2_dnd/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalContext
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
Expand All @@ -26,98 +26,98 @@ import dev.robin.flip_2_dnd.ui.theme.Flip_2_DNDTheme

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val mainViewModel: MainViewModel by viewModels()
private val dndPermissionLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
checkAndStartService()
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
checkAndStartService()

setContent {
Flip_2_DNDTheme {
val navController = rememberNavController()

NavHost(
navController = navController,
startDestination = "main"
) {
composable("main") {
val state by mainViewModel.state.collectAsState()
MainScreen(
state = state,
onSettingsClick = {
navController.navigate("settings")
}
)
}
composable("settings") {
SettingsScreen(
navController = navController
)
}
}
}
}
}

private fun checkAndStartService() {
val notificationPolicyGranted = isNotificationPolicyAccessGranted()
val batteryOptimizationDisabled = isBatteryOptimizationDisabled()

// Always start the service
startFlipDetectorService()

// If permissions are not granted, show a warning
if (!notificationPolicyGranted || !batteryOptimizationDisabled) {
// Optional: Add a toast or dialog to inform user about missing permissions
Toast.makeText(
this,
"Please grant all permissions for full functionality",
Toast.LENGTH_LONG
).show()

if (!notificationPolicyGranted) {
requestNotificationPolicyAccess()
}

if (!batteryOptimizationDisabled) {
requestDisableBatteryOptimization()
}
}
}

private fun isNotificationPolicyAccessGranted(): Boolean {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
return notificationManager.isNotificationPolicyAccessGranted
}

private fun requestNotificationPolicyAccess() {
val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)
dndPermissionLauncher.launch(intent)
}

private fun isBatteryOptimizationDisabled(): Boolean {
val powerManager = getSystemService(POWER_SERVICE) as PowerManager
return powerManager.isIgnoringBatteryOptimizations(packageName)
}

private fun requestDisableBatteryOptimization() {
val intent = Intent().apply {
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
data = Uri.parse("package:$packageName")
}
startActivity(intent)
}

private fun startFlipDetectorService() {
Intent(this, FlipDetectorService::class.java).also { intent ->
startForegroundService(intent)
}
}
private val mainViewModel: MainViewModel by viewModels()

private val dndPermissionLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
checkAndStartService()
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
checkAndStartService()

setContent {
Flip_2_DNDTheme {
val navController = rememberNavController()

NavHost(
navController = navController,
startDestination = "main"
) {
composable("main") {
val state by mainViewModel.state.collectAsState()
MainScreen(
state = state,
onSettingsClick = {
navController.navigate("settings")
}
)
}
composable("settings") {
SettingsScreen(
navController = navController
)
}
}
}
}
}

private fun checkAndStartService() {
val notificationPolicyGranted = isNotificationPolicyAccessGranted()
val batteryOptimizationDisabled = isBatteryOptimizationDisabled()

// Always start the service
startFlipDetectorService()

// If permissions are not granted, show a warning
if (!notificationPolicyGranted || !batteryOptimizationDisabled) {
// Optional: Add a toast or dialog to inform user about missing permissions
Toast.makeText(
this,
"Please grant all permissions for full functionality",
Toast.LENGTH_LONG
).show()

if (!notificationPolicyGranted) {
requestNotificationPolicyAccess()
}

if (!batteryOptimizationDisabled) {
requestDisableBatteryOptimization()
}
}
}

private fun isNotificationPolicyAccessGranted(): Boolean {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
return notificationManager.isNotificationPolicyAccessGranted
}

private fun requestNotificationPolicyAccess() {
val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)
dndPermissionLauncher.launch(intent)
}

private fun isBatteryOptimizationDisabled(): Boolean {
val powerManager = getSystemService(POWER_SERVICE) as PowerManager
return powerManager.isIgnoringBatteryOptimizations(packageName)
}

private fun requestDisableBatteryOptimization() {
val intent = Intent().apply {
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
data = Uri.parse("package:$packageName")
}
startActivity(intent)
}

private fun startFlipDetectorService() {
Intent(this, FlipDetectorService::class.java).also { intent ->
startForegroundService(intent)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import dagger.hilt.android.qualifiers.ApplicationContext
import dev.robin.flip_2_dnd.domain.model.PhoneOrientation
import dev.robin.flip_2_dnd.domain.repository.OrientationRepository
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import javax.inject.Inject
Expand All @@ -16,39 +16,39 @@ import kotlin.math.abs

@Singleton
class OrientationRepositoryImpl @Inject constructor(
@ApplicationContext private val context: Context
@ApplicationContext private val context: Context
) : OrientationRepository, SensorEventListener {

private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
private val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
private val _orientation = MutableStateFlow(PhoneOrientation.UNKNOWN)

override fun getOrientation(): Flow<PhoneOrientation> = _orientation

override suspend fun startMonitoring() {
sensorManager.registerListener(
this,
accelerometer,
SensorManager.SENSOR_DELAY_NORMAL
)
}

override suspend fun stopMonitoring() {
sensorManager.unregisterListener(this)
}

override fun onSensorChanged(event: SensorEvent?) {
if (event?.sensor?.type == Sensor.TYPE_ACCELEROMETER) {
val z = event.values[2]
_orientation.value = when {
abs(z) > 8.0f && z < 0 -> PhoneOrientation.FACE_DOWN
// abs(z) > 9.0f && z > 0 -> PhoneOrientation.FACE_UP
else -> PhoneOrientation.FACE_UP
}
}
}

override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
// Not needed for this implementation
}
private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
private val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
private val _orientation = MutableStateFlow(PhoneOrientation.UNKNOWN)

override fun getOrientation(): Flow<PhoneOrientation> = _orientation

override suspend fun startMonitoring() {
sensorManager.registerListener(
this,
accelerometer,
SensorManager.SENSOR_DELAY_NORMAL
)
}

override suspend fun stopMonitoring() {
sensorManager.unregisterListener(this)
}

override fun onSensorChanged(event: SensorEvent?) {
if (event?.sensor?.type == Sensor.TYPE_ACCELEROMETER) {
val z = event.values[2]
_orientation.value = when {
abs(z) > 9.5f && z < 0 -> PhoneOrientation.FACE_DOWN
// abs(z) > 9.0f && z > 0 -> PhoneOrientation.FACE_UP
else -> PhoneOrientation.FACE_UP
}
}
}

override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
// Not needed for this implementation
}
}
Loading

0 comments on commit 728f4e4

Please sign in to comment.