Add full screen android intent for alarm

This commit is contained in:
Brandon Presley 2022-10-18 21:38:06 +13:00
parent dc84fa5f6c
commit d21e7986e3
11 changed files with 333 additions and 9 deletions

View File

@ -131,6 +131,9 @@ android {
}
}
}
buildFeatures {
viewBinding true
}
buildTypes {
debug {
signingConfig signingConfigs.debug
@ -144,6 +147,8 @@ android {
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.4.+'
def work_version = "2.7.1"
implementation "androidx.work:work-runtime:$work_version"

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.massive">
@ -7,16 +8,30 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission tools:node="remove" android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE"
tools:node="remove" />
<application
android:name=".MainApplication"
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme"
android:dataExtractionRules="@xml/data_extraction_rules">
android:theme="@style/AppTheme">
<activity
android:name=".Fullscreen"
android:configChanges="orientation|keyboardHidden|screenSize"
android:exported="false"
android:label="@string/title_activity_fullscreen"
android:theme="@style/AppTheme.Fullscreen" />
<activity
android:name=".FullscreenActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:exported="false"
android:label="@string/title_activity_fullscreen"
android:theme="@style/AppTheme.Fullscreen" />
<activity
android:name=".MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
@ -25,12 +40,25 @@
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:exported="true" android:process=":remote" android:name=".StopAlarm" />
<service android:name=".StopTimer" android:exported="true" android:process=":remote" />
<service android:name=".AlarmService" android:exported="true" />
<service android:name=".TimerService" android:exported="true" />
<activity
android:name=".StopAlarm"
android:exported="true"
android:process=":remote" />
<service
android:name=".StopTimer"
android:exported="true"
android:process=":remote" />
<service
android:name=".AlarmService"
android:exported="true" />
<service
android:name=".TimerService"
android:exported="true" />
</application>
</manifest>
</manifest>

View File

@ -0,0 +1,185 @@
package com.massive
import androidx.appcompat.app.AppCompatActivity
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.WindowInsets
import android.widget.LinearLayout
import android.widget.TextView
import com.massive.databinding.ActivityFullscreenBinding
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*/
class Fullscreen : AppCompatActivity() {
private lateinit var binding: ActivityFullscreenBinding
private lateinit var fullscreenContent: TextView
private lateinit var fullscreenContentControls: LinearLayout
private val hideHandler = Handler(Looper.myLooper()!!)
@SuppressLint("InlinedApi")
private val hidePart2Runnable = Runnable {
// Delayed removal of status and navigation bar
if (Build.VERSION.SDK_INT >= 30) {
fullscreenContent.windowInsetsController?.hide(WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars())
} else {
// Note that some of these constants are new as of API 16 (Jelly Bean)
// and API 19 (KitKat). It is safe to use them, as they are inlined
// at compile-time and do nothing on earlier devices.
fullscreenContent.systemUiVisibility =
View.SYSTEM_UI_FLAG_LOW_PROFILE or
View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
}
}
private val showPart2Runnable = Runnable {
// Delayed display of UI elements
supportActionBar?.show()
fullscreenContentControls.visibility = View.VISIBLE
}
private var isFullscreen: Boolean = false
private val hideRunnable = Runnable { hide() }
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
* while interacting with activity UI.
*/
private val delayHideTouchListener = View.OnTouchListener { view, motionEvent ->
when (motionEvent.action) {
MotionEvent.ACTION_DOWN -> if (AUTO_HIDE) {
delayedHide(AUTO_HIDE_DELAY_MILLIS)
}
MotionEvent.ACTION_UP -> view.performClick()
else -> {
}
}
false
}
private fun stop() {
Log.d("Fullscreen", "Stopping...")
applicationContext.stopService(Intent(applicationContext, TimerService::class.java))
applicationContext.stopService(Intent(applicationContext, AlarmService::class.java))
val intent = Intent(applicationContext, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
applicationContext.startActivity(intent)
}
@SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityFullscreenBinding.inflate(layoutInflater)
setContentView(binding.root)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
isFullscreen = true
// Set up the user interaction to manually show or hide the system UI.
fullscreenContent = binding.fullscreenContent
fullscreenContent.setOnClickListener { toggle() }
fullscreenContentControls = binding.fullscreenContentControls
// Upon interacting with UI controls, delay any scheduled hide()
// operations to prevent the jarring behavior of controls going away
// while interacting with the UI.
binding.dummyButton.setOnTouchListener(delayHideTouchListener)
binding.dummyButton.setOnClickListener {
stop()
}
binding.fullscreenContent.setOnClickListener {
stop()
}
}
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
delayedHide(100)
}
private fun toggle() {
if (isFullscreen) {
hide()
} else {
show()
}
}
private fun hide() {
// Hide UI first
supportActionBar?.hide()
fullscreenContentControls.visibility = View.GONE
isFullscreen = false
// Schedule a runnable to remove the status and navigation bar after a delay
hideHandler.removeCallbacks(showPart2Runnable)
hideHandler.postDelayed(hidePart2Runnable, UI_ANIMATION_DELAY.toLong())
}
private fun show() {
// Show the system bar
if (Build.VERSION.SDK_INT >= 30) {
fullscreenContent.windowInsetsController?.show(WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars())
} else {
fullscreenContent.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
}
isFullscreen = true
// Schedule a runnable to display UI elements after a delay
hideHandler.removeCallbacks(hidePart2Runnable)
hideHandler.postDelayed(showPart2Runnable, UI_ANIMATION_DELAY.toLong())
}
/**
* Schedules a call to hide() in [delayMillis], canceling any
* previously scheduled calls.
*/
private fun delayedHide(delayMillis: Int) {
hideHandler.removeCallbacks(hideRunnable)
hideHandler.postDelayed(hideRunnable, delayMillis.toLong())
}
companion object {
/**
* Whether or not the system UI should be auto-hidden after
* [AUTO_HIDE_DELAY_MILLIS] milliseconds.
*/
private const val AUTO_HIDE = true
/**
* If [AUTO_HIDE] is set, the number of milliseconds to wait after
* user interaction before hiding the system UI.
*/
private const val AUTO_HIDE_DELAY_MILLIS = 3000
/**
* Some older devices needs a small delay between UI widget updates
* and a change of the status and navigation bar.
*/
private const val UI_ANIMATION_DELAY = 300
}
}

View File

@ -73,12 +73,20 @@ class TimerService : Service() {
finishIntent,
PendingIntent.FLAG_IMMUTABLE
)
val fullIntent = Intent(applicationContext, Fullscreen::class.java)
val fullPending =
PendingIntent.getActivity(
applicationContext,
0,
fullIntent,
PendingIntent.FLAG_IMMUTABLE
)
builder.setContentText("Timer finished.")
.setProgress(0, 0, false)
.setAutoCancel(true)
.setOngoing(true)
.setFullScreenIntent(fullPending, true)
.setContentIntent(finishPending)
.setFullScreenIntent(finishPending, true)
.setChannelId(CHANNEL_ID_DONE)
.setCategory(NotificationCompat.CATEGORY_ALARM)
.priority = NotificationCompat.PRIORITY_HIGH

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/fullscreenBackgroundColor"
android:theme="@style/ThemeOverlay.Massive.FullscreenContainer"
tools:context=".Fullscreen">
<!-- The primary full-screen view. This can be replaced with whatever view
is needed to present your content, e.g. VideoView, SurfaceView,
TextureView, etc. -->
<TextView
android:id="@+id/fullscreen_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:keepScreenOn="true"
android:text="@string/rest_timer_up"
android:textColor="?attr/fullscreenTextColor"
android:textSize="50sp"
android:textStyle="bold" />
<!-- This FrameLayout insets its children based on system windows using
android:fitsSystemWindows. -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:id="@+id/fullscreen_content_controls"
style="@style/Widget.AppTheme.ButtonBar.Fullscreen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:orientation="horizontal"
tools:ignore="UselessParent">
<Button
android:id="@+id/dummy_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/stop" />
</LinearLayout>
</FrameLayout>
</FrameLayout>

View File

@ -0,0 +1,7 @@
<resources>
<style name="ThemeOverlay.Massive.FullscreenContainer" parent="">
<item name="fullscreenBackgroundColor">@color/light_blue_900</item>
<item name="fullscreenTextColor">@color/light_blue_A400</item>
</style>
</resources>

View File

@ -0,0 +1,6 @@
<resources>
<declare-styleable name="FullscreenAttrs">
<attr name="fullscreenBackgroundColor" format="color" />
<attr name="fullscreenTextColor" format="color" />
</declare-styleable>
</resources>

View File

@ -0,0 +1,7 @@
<resources>
<color name="light_blue_600">#FF039BE5</color>
<color name="light_blue_900">#FF01579B</color>
<color name="light_blue_A200">#FF40C4FF</color>
<color name="light_blue_A400">#FF00B0FF</color>
<color name="black_overlay">#66000000</color>
</resources>

View File

@ -1,3 +1,8 @@
<resources>
<string name="app_name">Massive</string>
<string name="title_activity_fullscreen">FullscreenActivity</string>
<string name="dummy_button">Dummy Button</string>
<string name="dummy_content">DUMMY\nCONTENT</string>
<string name="rest_timer_up">Rest timer up</string>
<string name="stop">STOP</string>
</resources>

View File

@ -6,4 +6,13 @@
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
</style>
<style name="Widget.AppTheme.ActionBar.Fullscreen" parent="Widget.AppCompat.ActionBar">
<item name="android:background">@color/black_overlay</item>
</style>
<style name="Widget.AppTheme.ButtonBar.Fullscreen" parent="">
<item name="android:background">@color/black_overlay</item>
<item name="android:buttonBarStyle">?android:attr/buttonBarStyle</item>
</style>
</resources>

View File

@ -0,0 +1,13 @@
<resources>
<style name="AppTheme.Fullscreen" parent="AppTheme">
<item name="android:actionBarStyle">@style/Widget.AppTheme.ActionBar.Fullscreen</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowBackground">@null</item>
</style>
<style name="ThemeOverlay.Massive.FullscreenContainer" parent="">
<item name="fullscreenBackgroundColor">@color/light_blue_600</item>
<item name="fullscreenTextColor">@color/light_blue_A200</item>
</style>
</resources>