I have set a button click for some background API service to execute and after 3 clicks,I want the button to be disabled and only enabled after 24 hours.I did the following code but it is failed to be disabled.Here...
companion object {
var clickCount = 0
const val SAVED_TIME = "Time is saved"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val convert: Button = findViewById(R.id.Cbutton)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
inputAmount = findViewById(R.id.editText)
inputAmount!!.textSize = 30f
spin = findViewById(R.id.spin)
birr = findViewById(R.id.converted)
birr!!.text = getString(R.string.initialValue)
progressIndicator = findViewById(R.id.progressBar)
statusBarColorChange()
connectionStatusUpdate()
currencyListAdapterExecute()
convert.setOnClickListener {
val sharedPrefs = applicationContext.getSharedPreferences(SAVED_TIME,Context.MODE_PRIVATE)
if (inputAmount!!.text.isNotEmpty() && connected) {
val dateNow = Date().time
val savedDateTime = sharedPrefs.getLong("time",0)
if(savedDateTime == dateNow){
convert.isEnabled = false
}
clickCount += 1
if(clickCount < 4){
FetchedJsonData(this).execute()
}
else {
val exactTime = Date().time
sharedPrefs.edit().putLong("time",exactTime).apply()
}
}
You can store time in shared preference by following code.
SharedPreferences settings = c.getSharedPreferences(PREFS_NAME, 1);
SharedPreferences.Editor editor = settings.edit();
editor.putString("click_time", your_time);
Whenever need to compare, just compare your current time with the time stored in preference. Check if difference between time is less than 24 hours or not.
TO get time from prefernce:
SharedPreferences settings = c.getSharedPreferences(PREFS_NAME, 1);
String storedTime=settings.getString("clic_time", "");
Get difference in hours:
Date current, Date previous;
long diff = current.getTime() - previous.getTime();
long hours= diff / (60*60 * 1000);
To show timer, when app comes from background, you can get time from preference and start timer by using difference between 2 times.
Related
I have a TodoList App and I have a reminder feature in the fragment where you add your Todo, Meanwhile in another fragment the set Reminder is shown for that particular Task that was created. I want to be able to change the color of the Reminder to red when the Alarm set by the USER is Overdue or has been triggered. I was able to do the first but not the second. Is there a way I can check if the Alarm for that Todo has been Triggered(because the color for the second situation only changes when I recreate the view) in REAL TIME and then update it in the ListFragment changing the color of the Alarm to red. The Solutions I have tried in Stack Overflow here don't seem to work and is in a different language.
A picture of it.
My Alarm and Notifications code in my AddFragment
private fun scheduleNotification() {
val title = binding.edTaskTitle.text.toString()
val intent = Intent(requireContext().applicationContext , Notifications::class.java).apply {
putExtra(TITLE_EXTRA, title)
}
val pendingIntent = PendingIntent.getBroadcast(
requireContext().applicationContext,
NOTIFICATION_ID,
intent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val alarmManager = requireContext().getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.setAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
setDateTime,
pendingIntent
)
}
This is my bind function in my Adapter(My Adapter is in a separate file from my Fragment). In my Adapter is where I wrote the Implementation for changing the color of the reminder text if the Initial reminder set by the User is past the current Time(Overdue).
#SuppressLint("DiscouragedPrivateApi")
fun bind(todo : Todo) {
val dateLocales = SimpleDateFormat(SIMPLE_DATE_FORMAT, Locale.getDefault())
val timeLocales = SimpleDateFormat(SIMPLE_TIME_FORMAT, Locale.getDefault())
binding.apply {
tvTaskTitle.text = todo.title
tvTaskDate.text = dateLocales.format(todo.date)
tvTaskTime.text = timeLocales.format(todo.time)
cbTask.isChecked = todo.completed
tvTaskTitle.paint.isStrikeThruText = todo.completed
tvResultsReminder.isVisible = todo.important
// Will only show the resultsReminder if important is true
if (todo.important) {
tvResultsReminder.text = DateUtils.getRelativeDateTimeString(_context, todo.reminder.time, DateUtils.DAY_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0)
val date = Date()
val drawable : Drawable? = ContextCompat.getDrawable(_context, R.drawable.ic_alarm_reminder)
if (todo.reminder.time < date.time) {
tvResultsReminder.setTextColor(ContextCompat.getColor(_context, R.color.red))
}
}
// Implementing our PopupMenus to Edit and Delete a Task
iMenus.setOnClickListener { view ->
val popupMenus = PopupMenu(_context, view)
popupMenus.inflate(R.menu.show_menu)
popupMenus.setOnMenuItemClickListener {
when(it.itemId) {
R.id.itEditTask -> {
val action = ListFragmentDirections.actionListFragmentToUpdateFragment(todo)
itemView.findNavController().navigate(action)
true
}
R.id.itDeleteTask -> {
val position = adapterPosition// this represents the position of any item in the root layout
// NO_POSITION means that an item is invalid and out of this list, so this is a safe check because-
// we don't want to call a listener on an invalid item
if (position != RecyclerView.NO_POSITION) {
val curTodo = getItem(position)
listener.onItemDelete(curTodo)
}
Toast.makeText(_context, "Task has been deleted.", Toast.LENGTH_LONG).show()
true
}
else -> true
}
}
popupMenus.show()
val popup = PopupMenu::class.java.getDeclaredField("mPopup")
popup.isAccessible = true
val menu = popup.get(popupMenus)
menu.javaClass.getDeclaredMethod("setForceShowIcon", Boolean::class.java)
.invoke(menu, true)
}
}
}
}
And then I passed in a Column "triggered" in my Todo Class to record the state of the triggered Alarm to know what to do as the supposed Solution.
#Parcelize
#Entity(tableName = "todo_table")
data class Todo(
#PrimaryKey (autoGenerate = true) // here "Room" will autoGenerate the id for us instead of assigning a randomUUID value
val id : Int = 0,
val title : String = "",
var date : Date = Date(),
var time : Date = Date(),
var reminder : Date = Date(),
var important : Boolean = false,
var completed : Boolean = false,
val triggered : Boolean = false,
val created : Long = System.currentTimeMillis()
) : Parcelable
Another issue is that even I were able to do this. How would I in REAL TIME without recreating the view or doing something else be aware that the state of the Triggered alarm has been changed to then change the color of the text. It just seems so difficult.
so I have this problem where I am trying to make Random Number Generator app on android. Basically you set the minimum and the maximum number and then it randomly picks numbers between min and max.
However my problem comes if the min or max TextEdit field is empty, the app crashes. I would like to display "X" on the screen. How to check if the field is empty or not?
I am using kotlin and here is sample of my code. I am begginer so please do not flame me if the code is wrong :)
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rollButton = findViewById<Button>(R.id.rollButton)
val resultsTextView = findViewById<TextView>(R.id.resultsTextView)
//val seekBar = findViewById<SeekBar>(R.id.seekBar)
val min = findViewById<TextView>(R.id.number_min)
val max = findViewById<TextView>(R.id.number_max)
rollButton.setOnClickListener {
if(min.text.toString().toInt()>= 0 && max.text.toString().toInt() <= 1000){
val rand = Random.nextInt(min.text.toString().toInt(),max.text.toString().toInt()+1)
resultsTextView.text = rand.toString()
}
else if(min.text.toString().isNullOrBlank()){
resultsTextView.text = "X"
}
else{
resultsTextView.text = "X"
}
}
}
}
To check if your EditText is empty use isNullOrEmpty(). This will check if your field is empty or is null, like the method name says. Here is an example:
val editTextString :String = editText.text.toString()
if(!editTextString.isNullOrEmpty()) //returns true if string is null or empty
There is another approach with TextUtils but since you are using Kotlin this approach is better.
EDIT:
You are doing this:
if(min.text.toString().toInt()>= 0 && max.text.toString().toInt() <= 1000){
val rand = Random.nextInt(min.text.toString().toInt(),max.text.toString().toInt()+1)
resultsTextView.text = rand.toString()
}
and here this line min.text.toString().toInt() is throwing you an exception. The reason for this is because currently min or max are empty String. So compailer can't format number from an String equals to "". You should do it like this:
if(!min.text.toString().isNullOrEmpty() && !max.text.toString().isNullOrEmpty() && min.text.toString().toInt()>= 0 && max.text.toString().toInt() <= 1000){
val rand = Random.nextInt(min.text.toString().toInt(),max.text.toString().toInt()+1)
resultsTextView.text = rand.toString()
}
I hope this works. If not, then take this into two IF statements like this:
if(min.text.toString().isNullOrEmpty() || max.text.toString().isNullOrEmpty() {
resultsTextView.text = "X"
} else if(min.text.toString().toInt() >= 0 && max.text.toString().toInt() <= 1000) {
val rand = Random.nextInt(min.text.toString().toInt(), max.text.toString.toInt()+1)
resultsTextView.text = rand.toString()
}
The second approach is maybe an even better and cleaner version since you don't have to check for anything else later.
I am trying to pull a String value equal to the moment the chronometer stops as in "01:21" but the elapsed time gives an integer value, as in "11322".
val chronometer = findViewById<Chronometer>(R.id.chronometer)
chronometer.base = SystemClock.elapsedRealtime()
chronometer.format = "%s"
chronometer.start()
button.setOnClickListener {
val elapsedTime = SystemClock.elapsedRealtime() - chronometer.base
header.text = elapsedtime.toString()
Toast.makeText(this,"$elapsedTime",Toast.LENGTH_SHORT).show()
}
To be precise you get a long value and not an integer because both SystemClock.elapsedRealtime() and chronometer.base return a long value.
I have to disappoint you, currently there is no way to directly get the shown time of a chronometer, but of course you can convert the milliseconds you got to minutes and seconds, so you can show it again.
Here's my example of how it could work:
private fun calculateTime(chronometerMillis : Long) {
val minutes = TimeUnit.MILLISECONDS.toMinutes(chronometerMillis)
val seconds = TimeUnit.MILLISECONDS.toSeconds(chronometerMillis) - (minutes * 60)
println("Recreated time: $minutes:$seconds")
}
If you now call this method with the value 81000, which is 1 Minute and 21 Seconds (just like your chronometer), it prints Recreated time: 1:21.
To use it in your project just return a String:
private fun calculateTime(chronometerMillis : Long) : String {
val minutes = TimeUnit.MILLISECONDS.toMinutes(chronometerMillis)
val seconds = TimeUnit.MILLISECONDS.toSeconds(chronometerMillis) - (minutes * 60)
return "$minutes:$seconds"
}
private fun formattedChronometer(chronometer: Chronometer): String {
val elapsedTime = SystemClock.elapsedRealtime() - chronometer.base
val time = elapsedTime / 1000
val minutes = time / 60
val seconds = time % 60
return String.format("%02d:%02d",minutes,seconds)
}
Managed to solve it using this function after looking into the documentation
I'm working on timer app using kotlin. My requirement is to save multiple time values in preferences. For that purpose I have made a separate class for preferences.
This is the work done by me.
In PrefUtil class
private const val ElAPSED_TIME_VALUE_ID = "com.code.kotlin.elapsed_time"
private var incrementedValue = 0
fun getElapsedTime(context: Context) : Long {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
return preferences.getLong(ElAPSED_TIME_VALUE_ID , 0)
}
fun setElapsedTime(elapsedTime: Long, context: Context) {
val editor = PreferenceManager.getDefaultSharedPreferences(context).edit()
editor.putLong(ElAPSED_TIME_VALUE_ID, elapsedTime)
editor.apply()
}
On toggle button
btnToggle.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
startTimer()
timerState = TimerState.Running
showStartTime()
startingTime = System.currentTimeMillis()
PrefUtils.setStartTimeValue(startingTime, this)
Toast.makeText(applicationContext, "Timer is Running", Toast.LENGTH_SHORT).show()
} else {
timer.cancel()
onTimerFinished()
elapsedTime()
PrefUtils.getElapsedTime(this)
Toast.makeText(applicationContext, "Timer is Stopped", Toast.LENGTH_SHORT).show()
}
For saving elapsed time in preferences and then to get from there
private fun elapsedTime() {
val endingTime = System.currentTimeMillis()
val startTime = PrefUtils.getStartTimeValue(this)
elapsedTime = (-startTime + endingTime)
PrefUtils.setElapsedTime(elapsedTime, this)
}
private fun showElapsedTime() {
val minut = (PrefUtils.getElapsedTime(this) / 1000) / 60
val sec = (PrefUtils.getElapsedTime(this) / 1000) % 60
val elpTime: TextView = findViewById(R.id.elpTime)
elpTime.text = "Elapsed time: $minut : $sec "
}
On pressing pause button I want to show saved multiple time values..
fabPause.setOnClickListener {
timer.cancel()
timerState = TimerState.Paused
updateButtons()
showElapsedTime()
}
Now the problem is that when I close the app after getting one preference value the time value is automatically removed from preferences. On next session it is saved as new.. While I want to save and show multiple time values in multiple sessions. What should I do???
Need Your Help.......!
If you want to save all the timestamps using the same ElAPSED_TIME_VALUE_ID key, you can use e.g. SharedPreferences.Editor.putStringSet(). Or you can concat them to things like "timestamp1:timestamp2" then parse the string manually.
I'm trying to do a function that will only save a higher speed than the one already saved.
But the var outside the if loop is always 0.0, inside value is different. Does anyone knows some resolve or even better idea how to save only maximum speed?
private fun updateUI(speed: Double, distance: Double){
val df = DecimalFormat("0.0")
speed_text_view.text = df.format(speed).plus(" km/h")
distance_text_view.text = df.format(distance)
Log.e("getLocationUpdates", df.format(speed))
var getSpeedDouble = 0.0 //here is problem. The value doesn't change
if (speed > getSpeedDouble) {
val sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
val editor = sharedPref.edit()
editor
.putString("SPEED", speed.toString())
.apply()
val getSharedPref = PreferenceManager.getDefaultSharedPreferences(this)
getSharedPref.apply {
val getSpeed = getString("SPEED", "")
getSpeedDouble = getSpeed!!.toDouble()
Log.e("GetSpeedDouble", getSpeedDouble.toString())
max_speed_text_view.text = getSpeed.toString()
}
}
}
For posterity:
Have the speed as a global variable.
val speed:Double = 0.0
when you load the activity fetch its value from the shared preferences:
val preference = getSharedPreferences(yourApp, Context.MODE_PRIVATE)
val editor = preference.edit()
speed = preference.getDouble(“SPEED”,0.0)
when you finish the activity write the value back to the shared preferences:
editor.putDouble(“SPEED”,speed)
editor.commit()
within your method just assign a new value to the variable only if the current reading is bigger than the saved value.
private fun updateUI(newSpeed:Double) {
if (newSpeed > speed)
{
speed = newSpeed
textview.setText((newSpeed).toString())
}
}
How about putting it away in a nice class, and when just initializing that class from you activity:
speedKeeper = MaxSpeedKeeper(this)
then all you have to do is drop in your speeds (ie. speedKeeper.speed = 10.4) and it will stay updated.
Apply() will update to disk async, but the value in initialized sharedPref will stay cached, and is read from companion object's maxSpeed anyway.
This way, you can just drop your speedkeeper in any other processes, classes, fragments etc and it will keep doing what it does, or just initialize it again in a new activity.
class MaxSpeedKeeper(context: Context) {
companion object {
const val SPEED = "SPEED"
const val SHAREDPREFS_NAME = "MY_SHAREDPREFS"
var maxSpeed = 0.0f
}
var speed: Double
get() = maxSpeed.toDouble()
set(speedToCheck) {
if (speedToCheck > maxSpeed) {
maxSpeed=speedToCheck.toFloat()
with(sharedPref.edit()) {
putFloat(SPEED, speedToCheck.toFloat()) // you could change this to a string or bits or something if you want more resolution than a float gives
apply()
}
}
}
private val sharedPref =
context.getSharedPreferences(SHAREDPREFS_NAME, Context.MODE_PRIVATE)
init {
maxSpeed = sharedPref.getFloat(SPEED, 0.0f)
}
}
private fun updateUI(speed: Double) {
var getSpeedDouble = 0.0 //here is problem. The value doesn't change
if (speed > getSpeedDouble) {
val sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
val editor = sharedPref.edit()
editor.putString("SPEED", speed.toString()).apply()
val defaultSpeed = sharedPref.getString("SPEED", "")
getSpeedDouble = defaultSpeed.toString().toDouble()
Log.e("updateUI", getSpeedDouble.toString())
}
}
private fun getSpeed() {
var getSpeedDouble: Double
val sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
val defaultSpeed = sharedPref.getString("SPEED", "")
getSpeedDouble = defaultSpeed.toString().toDouble()
Log.e("getSpeed", getSpeedDouble.toString())
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
updateUI(10.0)
getSpeed()
}
output
updateUI: 10.0
getSpeed: 10.0