Showing posts with label Android code sample: Timer and TimerTask. Show all posts
Showing posts with label Android code sample: Timer and TimerTask. Show all posts

Wednesday, December 4, 2013

Start main activity after splash screen with animation

Modify from last exercise, in this post, we will start another activity (MainActivity) after animation of AnimationDrawable.

Start MainActivity after splash screen with animation


To start another activity, simple call startActivity() with intent.
   Intent intent = new Intent(
     AndroidAnimationActivity.this, MainActivity.class);
   startActivity(intent);


Create a new MainActivity.java, it's the new activity to run after splash screen. Simple display anything now.
package com.exercise.AndroidAnimation;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  ImageView image = new ImageView(this);
  image.setImageDrawable(
    getResources()
    .getDrawable(R.drawable.ic_launcher));
  setContentView(image);
 }
 
}


Modify run() method of MyTimerTask class in our splach screen activity, AndroidAnimationActivity.java in our example:
package com.exercise.AndroidAnimation;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.widget.ImageView;

public class AndroidAnimationActivity extends Activity {
    
 AnimationDrawable myAnimationDrawable;
 
 Timer timer;
 MyTimerTask myTimerTask;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        ImageView myAnimation = (ImageView)findViewById(R.id.myanimation);
        myAnimationDrawable 
         = (AnimationDrawable)myAnimation.getDrawable();

        myAnimation.post(
          new Runnable(){

     @Override
     public void run() {
      myAnimationDrawable.start();
     }
          });
        
        //Calculate the total duration
        int duration = 0;
        for(int i = 0; i < myAnimationDrawable.getNumberOfFrames(); i++){
         duration += myAnimationDrawable.getDuration(i);
        }
        
        timer = new Timer();
        myTimerTask = new MyTimerTask();
        timer.schedule(myTimerTask, duration);
    }
    
    class MyTimerTask extends TimerTask {

  @Override
  public void run() {
   
   timer.cancel();
   /*
   runOnUiThread(new Runnable(){
    @Override
    public void run() {
     Toast.makeText(getApplicationContext(), 
       "Animation Stopped", 
       Toast.LENGTH_SHORT).show(); 
    }});
   */
   Intent intent = new Intent(
     AndroidAnimationActivity.this, MainActivity.class);
   startActivity(intent);
  }  
 }
}


Modify AndroidManifest.xml to add <activity> of ".MainActivity".
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.exercise.AndroidAnimation"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AndroidAnimationActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
        </activity>
    </application>

</manifest>


From the demo video, it can be noted that:
- If the devie's configuration change (such as orientation) in MainActivity, it will still in MainActivity. Will not re-start the first activity.
- May be you have to special handle the BACK button depends on what you want, because of the first activity still in history stack in this simple implementation.

download filesDownload the files.

Tuesday, December 3, 2013

Handle end of animation for AnimationDrawable

I have a old exercise "Create frame animation with AnimationDrawable", which play animation repeatly without handle end of the animation. In this exercise, I will do something when the animation end.


AnimationDrawable have no any Listener for the end of animation, and also I cannot use the isRunning() method to determine the end of animation. Finally, I calculate the total duration of the animation using its getNumberOfFrames() and getDuration(). And then use Timer and TimerTask to schedule a Runnable() run when the time reached.

First of all, modify /res/anim/anim_android.xml to set android:oneshot="true", re-use the layout, main.xml, and the frame pictures. All of them can be found here.

Main code:
package com.exercise.AndroidAnimation;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.Toast;

public class AndroidAnimationActivity extends Activity {
    
 AnimationDrawable myAnimationDrawable;
 
 Timer timer;
 MyTimerTask myTimerTask;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        ImageView myAnimation = (ImageView)findViewById(R.id.myanimation);
        myAnimationDrawable 
         = (AnimationDrawable)myAnimation.getDrawable();

        myAnimation.post(
          new Runnable(){

     @Override
     public void run() {
      myAnimationDrawable.start();
     }
          });
        
        //Calculate the total duration
        int duration = 0;
        for(int i = 0; i < myAnimationDrawable.getNumberOfFrames(); i++){
         duration += myAnimationDrawable.getDuration(i);
        }
        
        timer = new Timer();
        myTimerTask = new MyTimerTask();
        timer.schedule(myTimerTask, duration);
    }
    
    class MyTimerTask extends TimerTask {

  @Override
  public void run() {
   
   timer.cancel();
   runOnUiThread(new Runnable(){
    @Override
    public void run() {
     Toast.makeText(getApplicationContext(), 
       "Animation Stopped", 
       Toast.LENGTH_SHORT).show(); 
    }});
  }  
 }
}



download filesDownload the files.

Next:
Start main activity after splash screen with animation

Example of using Timer and TimerTask on Android

This exercise show how to use java.util.Timer and java.util.TimerTask in Android programming.

java.util.Timer is a facility for threads to schedule tasks for future execution in a background thread. Tasks may be scheduled for one-time execution, or for repeated execution at regular intervals. java.util.TimerTask is a task that can be scheduled for one-time or repeated execution by a Timer.

Example of using Timer and TimerTask


package com.example.androidtimer;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {
 
 CheckBox optSingleShot;
 Button btnStart, btnCancel;
 TextView textCounter;
 
 Timer timer;
 MyTimerTask myTimerTask;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  optSingleShot = (CheckBox)findViewById(R.id.singleshot);
  btnStart = (Button)findViewById(R.id.start);
  btnCancel = (Button)findViewById(R.id.cancel);
  textCounter = (TextView)findViewById(R.id.counter);
  
  btnStart.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {

    if(timer != null){
     timer.cancel();
    }
    
    //re-schedule timer here
    //otherwise, IllegalStateException of
    //"TimerTask is scheduled already" 
    //will be thrown
    timer = new Timer();
    myTimerTask = new MyTimerTask();
    
    if(optSingleShot.isChecked()){
     //singleshot delay 1000 ms
     timer.schedule(myTimerTask, 1000);
    }else{
     //delay 1000ms, repeat in 5000ms
     timer.schedule(myTimerTask, 1000, 5000);
    }
   }});
  
  btnCancel.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    if (timer!=null){
     timer.cancel();
     timer = null;
    }
   }
  });
  
 }

 class MyTimerTask extends TimerTask {

  @Override
  public void run() {
   Calendar calendar = Calendar.getInstance();
   SimpleDateFormat simpleDateFormat = 
     new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
   final String strDate = simpleDateFormat.format(calendar.getTime());
   
   runOnUiThread(new Runnable(){

    @Override
    public void run() {
     textCounter.setText(strDate);
    }});
  }
  
 }

}


<LinearLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    <CheckBox 
        android:id="@+id/singleshot"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Single Shot"/>
 <Button 
     android:id="@+id/start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start"/>
 <Button 
     android:id="@+id/cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Cancel"/>
    <TextView
     android:id="@+id/counter"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="30dp"
        android:textStyle="bold"/>
</LinearLayout>


download filesDownload the files.