diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ef7e6b9..5cc194b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,12 +2,14 @@ - - + + + - + - + + + + android:stopWithTask="false" /> diff --git a/app/src/main/java/net/mezimmah/catflipscreen/CatFlipScreenApplication.kt b/app/src/main/java/net/mezimmah/catflipscreen/CatFlipScreenApplication.kt index 2dd4ed0..7ef62e6 100644 --- a/app/src/main/java/net/mezimmah/catflipscreen/CatFlipScreenApplication.kt +++ b/app/src/main/java/net/mezimmah/catflipscreen/CatFlipScreenApplication.kt @@ -26,6 +26,8 @@ class CatFlipScreenApplication : Application() { companion object { const val CHANNEL_ID = "autoStartServiceChannel" const val CHANNEL_NAME = "Auto Start Service Channel" + const val BROADCAST_BATTERY_CHANGED = "BROADCAST_BATTERY_CHANGED" + const val BROADCAST_AUDIO_MODE_CHANGED = "BROADCAST_AUDIO_MODE_CHANGED" } } \ No newline at end of file diff --git a/app/src/main/java/net/mezimmah/catflipscreen/FlipScreenService.kt b/app/src/main/java/net/mezimmah/catflipscreen/FlipScreenService.kt index 877e2a9..ff762a9 100644 --- a/app/src/main/java/net/mezimmah/catflipscreen/FlipScreenService.kt +++ b/app/src/main/java/net/mezimmah/catflipscreen/FlipScreenService.kt @@ -30,12 +30,12 @@ class FlipScreenService : Service() { override fun onTaskRemoved(rootIntent: Intent?) { val restartServiceIntent = Intent(applicationContext, FlipScreenService::class.java).also { it.setPackage(packageName) - }; + } val restartServicePendingIntent: PendingIntent = PendingIntent.getService(this, 1, restartServiceIntent, - PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE); - applicationContext.getSystemService(Context.ALARM_SERVICE); - val alarmService: AlarmManager = applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager; - alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000, restartServicePendingIntent); + PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE) + applicationContext.getSystemService(Context.ALARM_SERVICE) + val alarmService: AlarmManager = applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager + alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000, restartServicePendingIntent) } private fun showPresentationScreen() { @@ -59,6 +59,7 @@ class FlipScreenService : Service() { } private fun showNotification() { + val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val channel = NotificationChannel( CatFlipScreenApplication.CHANNEL_ID, diff --git a/app/src/main/java/net/mezimmah/catflipscreen/MainActivity.kt b/app/src/main/java/net/mezimmah/catflipscreen/MainActivity.kt index 7b103ce..f5eba06 100644 --- a/app/src/main/java/net/mezimmah/catflipscreen/MainActivity.kt +++ b/app/src/main/java/net/mezimmah/catflipscreen/MainActivity.kt @@ -1,11 +1,17 @@ package net.mezimmah.catflipscreen +import android.content.BroadcastReceiver +import android.content.Context import android.content.Intent +import android.content.IntentFilter import android.content.SharedPreferences +import android.media.AudioManager import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.preference.PreferenceFragmentCompat + class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -17,8 +23,34 @@ class MainActivity : AppCompatActivity() { .replace(R.id.settings, SettingsFragment()) .commit() } - startService(Intent(this, FlipScreenService::class.java)) + startForegroundService(Intent(this, FlipScreenService::class.java)) + registerReceivers() } + + private fun registerReceivers() { + val broadCastReceiver = object : BroadcastReceiver() { + override fun onReceive(contxt: Context, intent: Intent) { + when (intent.action) { + Intent.ACTION_POWER_CONNECTED, + Intent.ACTION_POWER_DISCONNECTED, + Intent.ACTION_BATTERY_CHANGED -> { + LocalBroadcastManager.getInstance(contxt) + .sendBroadcast(Intent(CatFlipScreenApplication.BROADCAST_BATTERY_CHANGED)) + } + AudioManager.RINGER_MODE_CHANGED_ACTION -> { + LocalBroadcastManager.getInstance(contxt) + .sendBroadcast(Intent(CatFlipScreenApplication.BROADCAST_AUDIO_MODE_CHANGED)) + } + } + } + } + this.registerReceiver(broadCastReceiver, IntentFilter(Intent.ACTION_POWER_CONNECTED)) + this.registerReceiver(broadCastReceiver, IntentFilter(Intent.ACTION_POWER_DISCONNECTED)) + this.registerReceiver(broadCastReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) + + this.registerReceiver(broadCastReceiver, IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION)) + } + class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.root_preferences, rootKey) diff --git a/app/src/main/java/net/mezimmah/catflipscreen/MyReceiver.kt b/app/src/main/java/net/mezimmah/catflipscreen/MyReceiver.kt index bd85868..47a5e6a 100644 --- a/app/src/main/java/net/mezimmah/catflipscreen/MyReceiver.kt +++ b/app/src/main/java/net/mezimmah/catflipscreen/MyReceiver.kt @@ -3,13 +3,21 @@ package net.mezimmah.catflipscreen import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import android.content.Intent.ACTION_BOOT_COMPLETED import android.util.Log class MyReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { + when (intent.action) { + ACTION_BOOT_COMPLETED -> startFlipScreenService(context) + } + } + + private fun startFlipScreenService(context: Context) { context.startService(Intent(context, FlipScreenService::class.java)) Log.i("Autostart", "started") } + } \ No newline at end of file diff --git a/app/src/main/java/net/mezimmah/catflipscreen/PresentationScreen.kt b/app/src/main/java/net/mezimmah/catflipscreen/PresentationScreen.kt index 806ff24..3355205 100644 --- a/app/src/main/java/net/mezimmah/catflipscreen/PresentationScreen.kt +++ b/app/src/main/java/net/mezimmah/catflipscreen/PresentationScreen.kt @@ -1,16 +1,173 @@ package net.mezimmah.catflipscreen import android.app.Presentation +import android.content.BroadcastReceiver import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.media.AudioManager +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest +import android.os.BatteryManager import android.os.Bundle import android.view.Display +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import androidx.localbroadcastmanager.content.LocalBroadcastManager + class PresentationScreen(outerContext: Context?, display: Display?) : Presentation(outerContext, display) { + private var connectivityManager: ConnectivityManager? = null + private var am: AudioManager? = null + private var batteryTextView: TextView? = null + private var batteryIconView: ImageView? = null + private var networkIconView: ImageView? = null + private var wifiIconView: ImageView? = null + private var audioLevelIconView: ImageView? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.layout_screen) + + findViews() + + getSystemServices() + + registerReceivers() + + updateBatteryLevel() + updateNetworkConnectivity() + updateAudioMode() + } + + private fun findViews() { + batteryTextView = findViewById(R.id.screen_status_bar_battery_level) + batteryIconView = findViewById(R.id.screen_status_bar_battery_icon) + networkIconView = findViewById(R.id.screen_status_bar_network_signal) + wifiIconView = findViewById(R.id.screen_status_bar_wifi_signal) + audioLevelIconView = findViewById(R.id.screen_status_bar_audio_level) + } + + private fun getSystemServices() { + am = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager? + connectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + } + + private fun registerReceivers() { + // Register receiver for Battery Status Update from the main activity + val broadCastReceiver = object : BroadcastReceiver() { + override fun onReceive(contxt: Context, intent: Intent) { + when (intent.action) { + CatFlipScreenApplication.BROADCAST_BATTERY_CHANGED -> { + updateBatteryLevel() + } + CatFlipScreenApplication.BROADCAST_AUDIO_MODE_CHANGED -> { + updateAudioMode() + } + } + } + } + LocalBroadcastManager.getInstance(context) + .registerReceiver(broadCastReceiver, IntentFilter(CatFlipScreenApplication.BROADCAST_BATTERY_CHANGED)) + LocalBroadcastManager.getInstance(context) + .registerReceiver(broadCastReceiver, IntentFilter(CatFlipScreenApplication.BROADCAST_AUDIO_MODE_CHANGED)) + + // Register receiver for the network updates + val networkRequest = NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .build() + val networkCallback = object : ConnectivityManager.NetworkCallback() { + // network is available for use + override fun onAvailable(network: Network) { + updateNetworkConnectivity() + super.onAvailable(network) + } + + // Network capabilities have changed for the network + override fun onCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities + ) { + super.onCapabilitiesChanged(network, networkCapabilities) + updateNetworkConnectivity() + } + + // lost network connection + override fun onLost(network: Network) { + super.onLost(network) + updateNetworkConnectivity() + } + } + connectivityManager?.requestNetwork(networkRequest, networkCallback) + } + + private fun updateBatteryLevel() { + val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter -> + context.registerReceiver(null, ifilter) + } + val status: Int = batteryStatus?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1 + val isCharging: Boolean = status == BatteryManager.BATTERY_STATUS_CHARGING + || status == BatteryManager.BATTERY_STATUS_FULL + + val batteryPct: Int = batteryStatus?.let { intent -> + val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) + val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1) + level * 100 / scale + }!! + batteryTextView!!.text = batteryPct.toString() + if (isCharging) { + batteryIconView!!.setImageResource(R.drawable.icons8_battery_50) + } else { + if (batteryPct < 15) { + batteryIconView!!.setImageResource(R.drawable.icons8_empty_battery_50) + } else if (batteryPct < 25) { + batteryIconView!!.setImageResource(R.drawable.icons8_low_battery_50) + } else if (batteryPct < 50) { + batteryIconView!!.setImageResource(R.drawable.icons8_battery_level_50) + } else if (batteryPct < 80) { + batteryIconView!!.setImageResource(R.drawable.icons8_charged_battery_50) + } else { + batteryIconView!!.setImageResource(R.drawable.icons8_full_battery_50) + } + } + } + + private fun updateNetworkConnectivity() { + networkIconView?.post { networkIconView?.visibility = View.GONE } + wifiIconView?.post { wifiIconView?.visibility = View.GONE } + if (connectivityManager != null) { + val capabilities = + connectivityManager?.getNetworkCapabilities(connectivityManager?.activeNetwork) + if (capabilities != null) { + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + networkIconView?.post { networkIconView?.visibility = View.VISIBLE } + } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { + wifiIconView?.post { wifiIconView?.visibility = View.VISIBLE } + } + } + } + } + + private fun updateAudioMode() { + when (am!!.ringerMode) { + AudioManager.RINGER_MODE_SILENT -> { + audioLevelIconView?.setImageResource(R.drawable.icons8_no_sound_50) + } + AudioManager.RINGER_MODE_VIBRATE -> { + audioLevelIconView?.setImageResource(R.drawable.icons8_vibration_48) + } + AudioManager.RINGER_MODE_NORMAL -> { + audioLevelIconView?.setImageResource(R.drawable.icons8_sound_50) + } + } } } diff --git a/app/src/main/res/drawable/icons8_battery_50.png b/app/src/main/res/drawable/icons8_battery_50.png new file mode 100644 index 0000000..5c1743e Binary files /dev/null and b/app/src/main/res/drawable/icons8_battery_50.png differ diff --git a/app/src/main/res/drawable/icons8_battery_level_50.png b/app/src/main/res/drawable/icons8_battery_level_50.png new file mode 100644 index 0000000..c462ab9 Binary files /dev/null and b/app/src/main/res/drawable/icons8_battery_level_50.png differ diff --git a/app/src/main/res/drawable/icons8_charged_battery_50.png b/app/src/main/res/drawable/icons8_charged_battery_50.png new file mode 100644 index 0000000..81a08c7 Binary files /dev/null and b/app/src/main/res/drawable/icons8_charged_battery_50.png differ diff --git a/app/src/main/res/drawable/icons8_empty_battery_50.png b/app/src/main/res/drawable/icons8_empty_battery_50.png new file mode 100644 index 0000000..a45b8a0 Binary files /dev/null and b/app/src/main/res/drawable/icons8_empty_battery_50.png differ diff --git a/app/src/main/res/drawable/icons8_full_battery_50.png b/app/src/main/res/drawable/icons8_full_battery_50.png new file mode 100644 index 0000000..8df6e44 Binary files /dev/null and b/app/src/main/res/drawable/icons8_full_battery_50.png differ diff --git a/app/src/main/res/drawable/icons8_low_battery_50.png b/app/src/main/res/drawable/icons8_low_battery_50.png new file mode 100644 index 0000000..71e2b36 Binary files /dev/null and b/app/src/main/res/drawable/icons8_low_battery_50.png differ diff --git a/app/src/main/res/drawable/icons8_no_sound_50.png b/app/src/main/res/drawable/icons8_no_sound_50.png new file mode 100644 index 0000000..ed671d5 Binary files /dev/null and b/app/src/main/res/drawable/icons8_no_sound_50.png differ diff --git a/app/src/main/res/drawable/icons8_signal_48.png b/app/src/main/res/drawable/icons8_signal_48.png new file mode 100644 index 0000000..7b150d6 Binary files /dev/null and b/app/src/main/res/drawable/icons8_signal_48.png differ diff --git a/app/src/main/res/drawable/icons8_sound_50.png b/app/src/main/res/drawable/icons8_sound_50.png new file mode 100644 index 0000000..442086c Binary files /dev/null and b/app/src/main/res/drawable/icons8_sound_50.png differ diff --git a/app/src/main/res/drawable/icons8_vibration_48.png b/app/src/main/res/drawable/icons8_vibration_48.png new file mode 100644 index 0000000..6369d18 Binary files /dev/null and b/app/src/main/res/drawable/icons8_vibration_48.png differ diff --git a/app/src/main/res/drawable/icons8_wifi_50.png b/app/src/main/res/drawable/icons8_wifi_50.png new file mode 100644 index 0000000..bf214eb Binary files /dev/null and b/app/src/main/res/drawable/icons8_wifi_50.png differ diff --git a/app/src/main/res/layout/layout_screen.xml b/app/src/main/res/layout/layout_screen.xml index e3ebf53..2edb19b 100644 --- a/app/src/main/res/layout/layout_screen.xml +++ b/app/src/main/res/layout/layout_screen.xml @@ -5,30 +5,79 @@ android:background="@color/black" android:orientation="vertical"> - - + android:layoutDirection="rtl" + android:layout_height="wrap_content"> + + + + + + + + + + + + + + + + android:textSize="22sp" /> + + \ No newline at end of file