How would you add an alarm to the CountDownTimer class? I guess it would be in the onFinish() method that comes with it, but just how would you go about that? Some code would help a lot.
Create a class that extends CountDownTimer, then override the on finish method and add a alarm function there.
object : NewCountDownTimer(3000, 1000) {
override fun onFinish() {
super.onFinish()
Timber.d("Test new countdowntimer2")
}
override fun onTick(millisUntilFinished: Long) {
}
}.start()
open class NewCountDownTimer(millisInFuture: Long, millisUntilFinished:Long) : CountDownTimer(millisInFuture, millisUntilFinished)
{
override fun onFinish() {
Timber.d("Test new countdowntimer")
//Add alarm function Here
}
override fun onTick(millisUntilFinished: Long) {
}
}
Related
I have this custom back press:
override fun onBackPressed() {
if (condition()) {
doSomething()
} else {
super.onBackPressed()
}
}
I can't seem to find a way to make it a OnBackPressedCallback,
private fun setupBackPress() {
onBackPressedDispatcher.addCallback(owner = this) {
if (condition()) {
doSomething()
} else {
onBackPressedDispatcher.onBackPressed()
// I don't know what to do in this case,
// this here would be an infinite loop
// but I need to just make it like super.onBackPressed()
}
}
}
Any ideas? thanks
How can I implement android media controls for the Notification Center when using MediaPlayer?
I tried to use the offical documentation right here and this article but I couldn't implement it correctly.
I tried to call this method when I start my media player mediaPlayer?.start(), but nothing is showing up in the notification center:
val mSession: MediaSession by lazy { MediaSession(requireContext(), "MusicService") }
fun createMediaControls() {
mSession.isActive = true
mSession.setCallback(object : MediaSession.Callback() {
override fun onMediaButtonEvent(mediaButtonIntent: Intent): Boolean {
print("onMediaButtonEvent called: $mediaButtonIntent")
return false
}
override fun onPause() {
print("onPause called (media button pressed)")
super.onPause()
}
override fun onPlay() {
print("onPlay called (media button pressed)")
super.onPlay()
}
override fun onStop() {
print("onStop called (media button pressed)")
super.onStop()
}
})
mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS or MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS)
mSession.setMetadata(
MediaMetadata.Builder()
.putString(MediaMetadata.METADATA_KEY_TITLE, "titleee")
.putString(MediaMetadata.METADATA_KEY_ARTIST, "artist")
.putString(MediaMetadata.METADATA_KEY_ALBUM_ART_URI, "albumArtUri")
.build()
)
}
I am using a Handler to display a timer in RecyclerView list item. When I press back the Activity that hosts the RecyclerView is completely destroyed, the Handler() still running in the background. The handler is created and initiated in ViewHolder. Is there any way to remove the callbacks from handler from ViewHolder itself?
My ViewHolder sample code
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), CustomRunnable.CustomRunnableListener{
private val handler = Handler()
lateinit var customRunnable: CustomRunnable //custom runnable for my timer logic
fun bind(position: Int, listModelClass: ModelClass?){
if(someCondition){
customRunnable = CustomRunnable(handler, this, textView, listModelClass)
handler.postDelayed(customRunnable, 1000)
}
}
override fun onTimerFinish(listModelClass: ModelClass) {
// I get this call back when the timer finishes
handler.removeCallbacks(customRunnable)
}
}
As per my knowledge, there is no method on adapter that is called when RecyclerView is detached from activity.
Try creating a timer object or a list of objects in your BaseActivity or Application Class and after pressing onBack run a method that will stop that timer or timers.
//Declare timer
CountDownTimer cTimer = null;
//start timer function
void startTimer() {
cTimer = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
}
};
cTimer.start();
}
//cancel timer
void cancelTimer() {
if(cTimer!=null)
cTimer.cancel();
}
You can do it onDestory() of activity
handler.removeCallbacksAndMessages(null);
Remove any pending posts of callbacks and sent messages whose obj is token. If token is null, all callbacks and messages will be removed.
if your Activity extended from androidx.activity.ComponentActivity, you can do this easily, just bind the lifecycle event then the super class would done their job as your desired, the sample code like below:
internal class SampleViewHolder(
private val activity: TheActivity,
view: View
) : RecyclerView.ViewHolder(view) {
fun bind(item: SampleInfo, position: Int) {
val view = itemView
...
bindLifecycle()
}
fun onViewRecycled() {
itemView.imv_sample.onViewRecycled(sampleAdapter.playStateStore)
activity.lifecycle.removeObserver(lifecycleObserver)
}
private val lifecycleObserver = object : LifecycleObserver {
#OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
private fun onDestroy() {
MLog.info(TAG, "receive destroy event")
itemView.imv_sample.onHostActivityDestroyed()
}
}
private fun bindLifecycle() {
activity.lifecycle.run {
MLog.info(TAG, "success bind lifecycle")
addObserver(lifecycleObserver)
}
}
}
When the activity is destroyed, set the list adapter to null. This will make sure onViewDetachedFromWindow is called for all the views in list when the activity is destroyed.
#Override
public void onDestroy() {
mList.setAdapter(null);
super.onDestroy();
}
And then you can remove the callbacks from the handler running inside the viewHolder. This requires you to save the handler reference inside your viewHolder.
#Override
public void onViewDetachedFromWindow(#NonNull PurchaseItemViewHolder holder) {
if (holder.handler != null) {
holder.handler.removeCallbacksAndMessages(null);
}
super.onViewDetachedFromWindow(holder);
}
I have this code in android studio:
The question is that if I give the button back and the main activity takes me, that is going to continue executing.
How do I make it so that once it's behind, it does not run what's in the onfinished?
new CountDownTimer (40000,1000) {
#Override
public void onTick(long l)
{
crono.setText("00:"+l/1000);
if(contador==10)
{
}
}
#Override
public void onFinish()
{
if(value.equals("tiempo"))
{
crono.setText("00:00");
}
else
{
esperar();
}
}
}.start();
CountDownTimer class help us to implement timer with custom time interval and duration. It provide 2 callback onTick(int millisUntilFinished) which called after each interval and onFinish is called when time duration is completed.
If you want to stop countdown then store instance countdown and call countdown.cancel() in onDestroy or button click(any where by user action)
You can refer this
Is there any way to trigger the SwipeRefreshLayout programmatically? The animation should start and the onRefresh method from the OnRefreshListener interface should get called.
if you are using the new swipeRefreshLayout intoduced in 5.0
As the image shown above you just need to add the following line to trigger the swipe refresh layout programmatically
Work
in Java:
mSwipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
}
});
on in Kotlin:
mSwipeRefreshLayout.post { mSwipeRefreshLayout.isRefreshing = true }
NOT work
if you simply call in Java:
mSwipeRefreshLayout.setRefreshing(true);
or in Kotlin
mSwipeRefreshLayout.isRefreshing = true
it won't trigger the circle to animate, so by adding the above line u just make a delay in the UI thread so that it shows the circle animation inside the ui thread.
By calling mSwipeRefreshLayout.setRefreshing(true) the OnRefreshListener will NOT get executed
In order to stop the circular loading animation call mSwipeRefreshLayout.setRefreshing(false)
In order to trigger SwipeRefreshLayout I tried this solution:
SwipeRefreshLayout.OnRefreshListener swipeRefreshListner = new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
Log.i(TAG, "onRefresh called from SwipeRefreshLayout");
// This method performs the actual data-refresh operation.
// The method calls setRefreshing(false) when it's finished.
loadData();
}
};
Now key part:
swipeLayout.post(new Runnable() {
#Override public void run() {
swipeLayout.setRefreshing(true);
// directly call onRefresh() method
swipeRefreshListner.onRefresh();
}
});
Simply create a SwipeRefreshLayout.OnRefreshListener and call its function onRefresh() whenever needed:
SwipeRefreshLayout srl;
SwipeRefreshLayout.OnRefreshListener refreshListener;
srl = (SwipeRefreshLayout)v.findViewById(R.id.swipeRefreshLayout);
refreshListener = new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
//Do your stuff here
}
};
srl.setOnRefreshListener(refreshListener);
Now, whenever you want to call it manually, just call it through the listener
refreshListener.onRefresh();
Bit late to the thread, but you do not need to launch a Runnable to do this. You can simply trigger the refresh and call your onRefresh method directly in onCreate, or wherever you want this to happen:
class MyFragment: SwipeRefreshLayout.OnRefreshListener {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
}
fun initViews() {
swipe_refresh_layout?.apply {
setOnRefreshListener(this#MyFragment)
isRefreshing = true
onRefresh()
}
}
override fun onRefresh() {
// Do my refresh logic here
}
}
binding.swipeRefreshLayout.setRefreshing(true); // show loading
binding.swipeRefreshLayout.post(this::updateUI); // call method
binding.swipeRefreshLayout.setOnRefreshListener(this::updateUI); // call method
You can call onRefresh() method programmatically and then inside the method start the animation if it is not already started. See the following:
#Override
public void onRefresh() {
if (!mSwipeRefreshLayout.isRefreshing()) mSwipeRefreshLayout.setRefreshing(true);
//TODO
}
Just to force in add this two to ennable swipe gesture
swipeRefreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
Log.i(TAG, "onRefresh called from SwipeRefreshLayout");
// This method performs the actual data-refresh operation.
// The method calls setRefreshing(false) when it's finished.
FetchData();
}
}
);