Skip to content
Snippets Groups Projects
Commit 4aa61ba4 authored by Eun Jegal's avatar Eun Jegal
Browse files

Lab7 Added

parent 002789cb
No related branches found
No related tags found
No related merge requests found
Showing
with 334 additions and 0 deletions
...@@ -57,6 +57,7 @@ class MainActivity : AppCompatActivity() { ...@@ -57,6 +57,7 @@ class MainActivity : AppCompatActivity() {
// [Hint] Access TextViews using "binding" object like we did with "secondActivityLaunchBtn" // [Hint] Access TextViews using "binding" object like we did with "secondActivityLaunchBtn"
// Only need 4 lines of code, one TextView for each counter variable // Only need 4 lines of code, one TextView for each counter variable
binding.onCreate.setText("hello")
} }
private fun restoreCounts (savedInstanceState:Bundle) { private fun restoreCounts (savedInstanceState:Bundle) {
......
File added
File added
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'androidx.navigation.safeargs'
}
android {
compileSdkVersion build_versions.compile_sdk
defaultConfig {
minSdkVersion build_versions.min_sdk
targetSdkVersion build_versions.target_sdk
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation deps.core_ktx
implementation deps.activity.activity_ktx
implementation deps.fragment.fragment_ktx
implementation deps.app_compat
implementation deps.material
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="course.labs.broadcastreceiverslab">
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.App">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
package course.labs.broadcastreceiverslab
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.lifecycle.ViewModelProvider
import course.labs.broadcastreceiverslab.databinding.MainActivityBinding
class MainActivity : AppCompatActivity() {
// This lab is for understanding BroadcastReceivers that responds to device status in runtime
// Update the period of pulsing image according to the device's charging status
// We need two main objects - 1)BroadcastReceiver and 2)ViewModel
// 1)BroadcastReceiver - Responds to the device's charging status
private lateinit var receiver: PowerConnectionStatusReceiver
// 2)ViewModel - Manages the pulsing period of the main image
// Get reference to CounterViewModel using viewModels delegate
private lateinit var viewModel: PowerStatusViewModel
// Binding to XML layout
private lateinit var binding: MainActivityBinding
// Handler for periodically pulsing image. Will cover in a later lecture.
// More details about Handler available at
// "https://developer.android.com/reference/android/os/Handler"
private lateinit var handler: Handler
// Pulsing period of the main image
private var pulsingRate = 0L
// Runnable for toggling image visibility
private val imageUpdater: Runnable = object : Runnable {
override fun run() {
// Update the image visibility for the pulsing effect
binding.image.visibility = if (binding.image.isVisible) View.INVISIBLE
else View.VISIBLE
// This will be repeated at regular interval which is defined with the "pulsingRate" parameter
handler.postDelayed(this, pulsingRate)
}
}
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Pass the root view to setContentView() to make it the active view on the screen
// More details about view binding available at
// "https://developer.android.com/topic/libraries/view-binding"
binding = MainActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
// Create handler to update the image visibility
handler = Handler(Looper.getMainLooper())
// Initialize viewModel
viewModel = ViewModelProvider(this)[PowerStatusViewModel::class.java]
// TODO :
// Create the receiver passing viewModel as a constructor parameter
// Observe changes to powerStatus
observeViewModelPowerStatus()
}
private fun observeViewModelPowerStatus() {
// Register observer of powerStatus
viewModel.isPowerConnected.observe(this) {
// TODO :
// The pulsing rate should be updated according to the viewModel value (isPowerConnected)
// [Hint] Use constant values - HIGH_SPEED, LOW_SPEED
// Handler would toggle the image visibility with the changed pulsing rate value
handler.run {
removeCallbacks(imageUpdater)
postDelayed(imageUpdater, pulsingRate)
}
}
}
override fun onStart() {
super.onStart()
Log.i(TAG, "onStart() called")
// TODO :
// Register receiver dynamically using IntentFilter
// 2 lines of codes need - Intent.ACTION_POWER_CONNECTED & Intent.ACTION_POWER_CONNECTED
}
// Update user interface by tracking power connection status
// [Note]
// Keep in mind that the screen needs to be updated when a user reenters the app
override fun onResume() {
super.onResume()
Log.i(TAG, "onResume() called")
// TODO :
// Get the current power connection status from the system
// Then update the value of viewModel's connection status
// [Hint] How to get connection status from Intent
// https://developer.android.com/training/monitoring-device-state/battery-monitoring
}
override fun onPause() {
super.onPause()
Log.i(TAG, "onPause() called")
// Stop the handler toggling image visibility
handler.removeCallbacks(imageUpdater)
}
override fun onStop() {
Log.i(TAG, "onStop() called")
// TODO :
// Unregister receiver dynamically
super.onStop()
}
companion object {
// Constant values for pulsing period
// HIGH_SPEED : Update the image visibility every 250ms
// LOW_SPEED : Update the image visibility every 1000ms(1s)
const val HIGH_SPEED = 250L
const val LOW_SPEED = 1000L
const val TAG = "Lab_BR"
}
}
\ No newline at end of file
package course.labs.broadcastreceiverslab
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
class PowerConnectionStatusReceiver(
private val viewModel: PowerStatusViewModel
) : BroadcastReceiver() {
// This class is for receiving messages of the device's power connection status from the Android system
override fun onReceive(context: Context?, intent: Intent?) {
// TODO :
// Update the viewModel's connection status value according using Intent action
}
}
\ No newline at end of file
package course.labs.broadcastreceiverslab
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class PowerStatusViewModel : ViewModel(), DefaultLifecycleObserver {
// Current connection status
var isPowerConnected: MutableLiveData<Boolean> = MutableLiveData<Boolean>()
}
\ No newline at end of file
Labs/Lab7_BroadcastReceivers/app/src/main/res/drawable-nodpi/b512.png

241 KiB

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/rippleColor">
<item>
<selector>
<item android:state_checked="true">
<color android:color="?attr/colorControlHighlight" />
</item>
</selector>
</item>
</ripple>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_margin">
<ImageView
android:id="@+id/image"
android:layout_width="@dimen/bubble_width"
android:layout_height="@dimen/bubble_width"
android:layout_gravity="center"
android:contentDescription="@string/bubble_desc"
app:srcCompat="@drawable/b512"
app:tint="@color/accent" />
</FrameLayout>
\ No newline at end of file
Labs/Lab7_BroadcastReceivers/app/src/main/res/mipmap-hdpi/ic_launcher.png

7.48 KiB

Labs/Lab7_BroadcastReceivers/app/src/main/res/mipmap-mdpi/ic_launcher.png

3.69 KiB

Labs/Lab7_BroadcastReceivers/app/src/main/res/mipmap-xhdpi/ic_launcher.png

12.2 KiB

Labs/Lab7_BroadcastReceivers/app/src/main/res/mipmap-xxhdpi/ic_launcher.png

24.2 KiB

<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.App" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/md_theme_dark_primary</item>
<item name="colorPrimaryVariant">@color/md_theme_dark_primaryContainer</item>
<item name="colorOnPrimary">@color/md_theme_dark_onPrimary</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/md_theme_dark_tertiary</item>
<item name="colorSecondaryVariant">@color/md_theme_dark_secondaryContainer</item>
<item name="colorOnSecondary">@color/md_theme_dark_onSecondary</item>
<item name="colorAccent">@color/md_theme_dark_tertiary</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<item name="android:selectableItemBackground" tools:targetApi="l">@drawable/background_selector</item>
<item name="rippleColor">@color/ripple_dark</item>
</style>
</resources>
\ No newline at end of file
<resources>
<color name="md_theme_light_primary">#2196F3</color>
<color name="md_theme_light_onPrimary">#FFFFFF</color>
<color name="md_theme_light_primaryContainer">#1976D2</color>
<color name="md_theme_light_onPrimaryContainer">#001D36</color>
<color name="md_theme_light_secondary">#005FB1</color>
<color name="md_theme_light_onSecondary">#FFFFFF</color>
<color name="md_theme_light_secondaryContainer">#D3E3FF</color>
<color name="md_theme_light_tertiary">#EF5350</color>
<color name="md_theme_dark_primary">#9BCAFF</color>
<color name="md_theme_dark_onPrimary">#226AA2</color>
<color name="md_theme_dark_primaryContainer">#00497E</color>
<color name="md_theme_dark_secondary">#A4C8FF</color>
<color name="md_theme_dark_onSecondary">#003060</color>
<color name="md_theme_dark_secondaryContainer">#004788</color>
<color name="md_theme_dark_tertiary">#CF7C77</color>
<color name="ripple_light">#40FFFFFF</color>
<color name="ripple_dark">#40000000</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<!-- Old colors -->
<color name="red">#CC0000</color>
<color name="green">#00FF00</color>
<color name="blue">#0000FF</color>
<color name="yellow">#FFFF00</color>
<color name="gold">#FFD700</color>
<color name="primary">#FF5722</color>
<color name="primary_dark">#E64A19</color>
<color name="primary_light">#FFCCBC</color>
<color name="primary_disabled">#FFF8AD96</color>
<color name="accent">#536DFE</color>
<color name="primary_text">#212121</color>
<color name="secondary_text">#757575</color>
<color name="icons">#FFFFFF</color>
<color name="divider">#BDBDBD</color>
<color name="edit_text">#202020</color>
<color name="black_text_87">#DE000000</color>
<color name="black_text_54">#8A000000</color>
<color name="background_color">#08237e</color>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_margin">16dp</dimen>
<dimen name="list_item_padding">8dp</dimen>
<dimen name="content_area_padding">8dp</dimen>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="bubble_width">250dp</dimen>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">BroadcastReceiversLab</string>
<string name="bubble_desc">Bubble</string>
</resources>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment