269 lines
11 KiB
Kotlin
269 lines
11 KiB
Kotlin
package com.example.shiftalarm
|
|
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.os.Bundle
|
|
import android.view.LayoutInflater
|
|
import android.view.View
|
|
import android.view.ViewGroup
|
|
import android.widget.ArrayAdapter
|
|
import android.widget.Toast
|
|
import androidx.fragment.app.Fragment
|
|
import com.example.shiftalarm.databinding.FragmentSettingsBasicBinding
|
|
import java.io.BufferedInputStream
|
|
import java.io.File
|
|
import java.io.FileOutputStream
|
|
import java.net.HttpURLConnection
|
|
import android.app.ProgressDialog
|
|
import android.net.Uri
|
|
import android.os.Build
|
|
import androidx.core.content.FileProvider
|
|
import androidx.lifecycle.lifecycleScope
|
|
import kotlinx.coroutines.launch
|
|
import android.provider.Settings
|
|
import androidx.core.content.ContextCompat
|
|
|
|
class FragmentSettingsBasic : Fragment() {
|
|
|
|
private var _binding: FragmentSettingsBasicBinding? = null
|
|
private val binding get() = _binding!!
|
|
|
|
private val PREFS_NAME = "ShiftAlarmPrefs"
|
|
private var isUserInteraction = false
|
|
|
|
override fun onCreateView(
|
|
inflater: LayoutInflater, container: ViewGroup?,
|
|
savedInstanceState: Bundle?
|
|
): View {
|
|
_binding = FragmentSettingsBasicBinding.inflate(inflater, container, false)
|
|
return binding.root
|
|
}
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
super.onViewCreated(view, savedInstanceState)
|
|
loadSettings()
|
|
setupListeners()
|
|
}
|
|
|
|
private fun loadSettings() {
|
|
val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
|
|
|
// Factory Spinner
|
|
setupFactorySpinner(prefs)
|
|
|
|
// Team Spinner
|
|
setupTeamSpinner(prefs)
|
|
|
|
// Version Info
|
|
try {
|
|
val pInfo = requireContext().packageManager.getPackageInfo(requireContext().packageName, 0)
|
|
binding.versionInfo.text = "Ver. ${pInfo.versionName} | 제작자: 산적이얌"
|
|
} catch (e: Exception) {
|
|
binding.versionInfo.text = "Ver. Unknown | 제작자: 산적이얌"
|
|
}
|
|
|
|
// Show/Hide Exact Alarm based on version
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
binding.btnExactAlarm.visibility = View.VISIBLE
|
|
binding.dividerExact.visibility = View.VISIBLE
|
|
} else {
|
|
binding.btnExactAlarm.visibility = View.GONE
|
|
binding.dividerExact.visibility = View.GONE
|
|
}
|
|
}
|
|
|
|
private fun setupFactorySpinner(prefs: android.content.SharedPreferences) {
|
|
val savedFactory = prefs.getString("selected_factory", "Jeonju")
|
|
val factoryIndex = if (savedFactory == "Nonsan") 1 else 0
|
|
binding.factorySpinner.setSelection(factoryIndex)
|
|
|
|
binding.factorySpinner.setOnTouchListener { _, _ ->
|
|
isUserInteraction = true
|
|
false
|
|
}
|
|
|
|
binding.factorySpinner.onItemSelectedListener = object : android.widget.AdapterView.OnItemSelectedListener {
|
|
override fun onItemSelected(parent: android.widget.AdapterView<*>?, view: View?, position: Int, id: Long) {
|
|
if (!isUserInteraction) return
|
|
|
|
val isNonsan = position == 1
|
|
val factory = if (isNonsan) "Nonsan" else "Jeonju"
|
|
|
|
val currentFactory = prefs.getString("selected_factory", "Jeonju")
|
|
if (factory == currentFactory) {
|
|
// Just update team spinner without resetting times if same factory
|
|
updateTeamSpinner(isNonsan)
|
|
return
|
|
}
|
|
|
|
// Save immediately
|
|
val editor = prefs.edit()
|
|
editor.putString("selected_factory", factory)
|
|
editor.apply()
|
|
|
|
// CRUCIAL: Re-sync all alarms for the new factory
|
|
lifecycleScope.launch {
|
|
syncAllAlarms(requireContext())
|
|
Toast.makeText(requireContext(), "공장 설정이 변경되었습니다.", Toast.LENGTH_SHORT).show()
|
|
}
|
|
|
|
// Update Team Spinner logic
|
|
updateTeamSpinner(isNonsan)
|
|
}
|
|
override fun onNothingSelected(parent: android.widget.AdapterView<*>?) {}
|
|
}
|
|
}
|
|
|
|
private fun updateTeamSpinner(isNonsan: Boolean) {
|
|
val currentSelection = binding.teamSpinner.selectedItemPosition
|
|
val teamOptions = if (isNonsan) {
|
|
arrayOf("A반", "B반", "C반")
|
|
} else {
|
|
arrayOf("A반", "B반", "C반", "D반")
|
|
}
|
|
|
|
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, teamOptions)
|
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
|
binding.teamSpinner.adapter = adapter
|
|
|
|
if (currentSelection < teamOptions.size) {
|
|
binding.teamSpinner.setSelection(currentSelection)
|
|
} else {
|
|
binding.teamSpinner.setSelection(0)
|
|
if (isUserInteraction) {
|
|
Toast.makeText(requireContext(), "논산 회사는 D반이 없습니다. A반으로 설정됩니다.", Toast.LENGTH_SHORT).show()
|
|
val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
|
prefs.edit().putString("selected_team", "A").apply()
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun setupTeamSpinner(prefs: android.content.SharedPreferences) {
|
|
val savedFactory = prefs.getString("selected_factory", "Jeonju")
|
|
val isNonsan = savedFactory == "Nonsan"
|
|
updateTeamSpinner(isNonsan)
|
|
|
|
val savedTeam = prefs.getString("selected_team", "A")
|
|
val teamIndex = when (savedTeam) {
|
|
"A" -> 0
|
|
"B" -> 1
|
|
"C" -> 2
|
|
"D" -> if (isNonsan) 0 else 3
|
|
else -> 0
|
|
}
|
|
binding.teamSpinner.setSelection(teamIndex)
|
|
|
|
binding.teamSpinner.setOnTouchListener { _, _ ->
|
|
isUserInteraction = true
|
|
false
|
|
}
|
|
|
|
binding.teamSpinner.onItemSelectedListener = object : android.widget.AdapterView.OnItemSelectedListener {
|
|
override fun onItemSelected(parent: android.widget.AdapterView<*>?, view: View?, position: Int, id: Long) {
|
|
if (!isUserInteraction) return
|
|
|
|
val selectedTeam = when(position) {
|
|
0 -> "A"
|
|
1 -> "B"
|
|
2 -> "C"
|
|
3 -> "D"
|
|
else -> "A"
|
|
}
|
|
prefs.edit().putString("selected_team", selectedTeam).apply()
|
|
|
|
// CRUCIAL: Re-sync all alarms for the new team
|
|
lifecycleScope.launch {
|
|
syncAllAlarms(requireContext())
|
|
Toast.makeText(requireContext(), "${selectedTeam}반으로 알람이 재설정되었습니다.", Toast.LENGTH_SHORT).show()
|
|
}
|
|
}
|
|
|
|
override fun onNothingSelected(parent: android.widget.AdapterView<*>?) {}
|
|
}
|
|
}
|
|
|
|
override fun onResume() {
|
|
super.onResume()
|
|
updatePermissionStatuses()
|
|
}
|
|
|
|
private fun updatePermissionStatuses() {
|
|
val context = requireContext()
|
|
|
|
// 1. 배터리 (Battery)
|
|
val isBatteryIgnored = AlarmPermissionUtil.getBatteryOptimizationStatus(context)
|
|
binding.tvBatteryStatus.text = if (isBatteryIgnored) "[설정 완료: 절전 예외]" else "클릭하여 '제한 없음'으로 설정하세요"
|
|
binding.tvBatteryStatus.setTextColor(ContextCompat.getColor(context, if (isBatteryIgnored) R.color.primary else R.color.shift_red))
|
|
|
|
// 2. 정확한 알람 (Exact Alarm) - Android 12+
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
val isExactGranted = AlarmPermissionUtil.getExactAlarmStatus(context)
|
|
binding.tvExactStatus.text = if (isExactGranted) "[설정 완료: 정밀 알람]" else "필수: 클릭하여 권한을 허용하세요"
|
|
binding.tvExactStatus.setTextColor(ContextCompat.getColor(context, if (isExactGranted) R.color.primary else R.color.shift_red))
|
|
} else {
|
|
binding.btnExactAlarm.visibility = View.GONE
|
|
binding.dividerExact.visibility = View.GONE
|
|
}
|
|
|
|
// 3. 다른 앱 위에 표시 (Overlay)
|
|
val isOverlayGranted = AlarmPermissionUtil.getOverlayStatus(context)
|
|
binding.tvOverlayStatus.text = if (isOverlayGranted) "[설정 완료: 화면 우위]" else "필수: 알람창 노출을 위해 허용하세요"
|
|
binding.tvOverlayStatus.setTextColor(ContextCompat.getColor(context, if (isOverlayGranted) R.color.primary else R.color.shift_red))
|
|
|
|
// 4. 전체화면 알림 (Full Screen Intent) - Android 14+
|
|
if (Build.VERSION.SDK_INT >= 34) {
|
|
val isFullScreenGranted = AlarmPermissionUtil.getFullScreenIntentStatus(context)
|
|
binding.tvFullScreenStatus.text = if (isFullScreenGranted) "[설정 완료: 전체화면]" else "필수: 안드로이드 14 이상 필수 설정"
|
|
binding.tvFullScreenStatus.setTextColor(ContextCompat.getColor(context, if (isFullScreenGranted) R.color.primary else R.color.shift_red))
|
|
binding.btnFullScreenIntent.visibility = View.VISIBLE
|
|
} else {
|
|
binding.btnFullScreenIntent.visibility = View.GONE
|
|
}
|
|
}
|
|
|
|
private fun setupListeners() {
|
|
val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
|
|
|
binding.btnBatteryOptimize.setOnClickListener {
|
|
AlarmPermissionUtil.requestBatteryOptimization(requireContext())
|
|
}
|
|
|
|
binding.btnExactAlarm.setOnClickListener {
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
val intent = Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM).apply {
|
|
data = Uri.parse("package:${requireContext().packageName}")
|
|
}
|
|
startActivity(intent)
|
|
}
|
|
}
|
|
|
|
binding.btnOverlayPermission.setOnClickListener {
|
|
AlarmPermissionUtil.requestOverlayPermission(requireContext())
|
|
}
|
|
|
|
binding.btnFullScreenIntent.setOnClickListener {
|
|
AlarmPermissionUtil.requestFullScreenIntentPermission(requireContext())
|
|
}
|
|
|
|
binding.btnPermissionSettings.setOnClickListener {
|
|
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
|
data = Uri.parse("package:${requireContext().packageName}")
|
|
}
|
|
startActivity(intent)
|
|
}
|
|
|
|
binding.btnCheckUpdate.setOnClickListener {
|
|
checkUpdate()
|
|
}
|
|
}
|
|
|
|
private fun checkUpdate() {
|
|
AppUpdateManager.checkUpdate(requireActivity(), silent = false)
|
|
}
|
|
|
|
override fun onDestroyView() {
|
|
super.onDestroyView()
|
|
_binding = null
|
|
}
|
|
}
|