Sunday, 17 May 2015

Blinking text animation in Android

Background

In last post we saw how to do a simple animation of bouncing ball. In this we will see how to make a text blink using ObjectAnimator. We will make text - "Hello World!" start and stop blinking using buttons.

Creating the Layout

 Create layout file - blinking_text_layout.xml and add following content in it.


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/startBlinkTextButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="Start Blinking Text" />

    <Button
        android:id="@+id/stopBlinkTextButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/startBlinkTextButton"
        android:layout_centerHorizontal="true"
        android:text="Stop Blinking Text" />

    <TextView
        android:id="@+id/blinkTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/stopBlinkTextButton"
        android:layout_centerHorizontal="true"
        android:paddingTop="10dp"
        android:text="Hello World!"
        android:textSize="40sp" />

</RelativeLayout>

The layout should get rendered on your phone as follows -



Now lets write code to animate this text.

Animate Blinking of Text

As you can see from the layout we have two buttons - one to start the blinking animation and other to stop it. Code is as follows - 


package com.osfg.animationdemo;

import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class AnimationStarter extends Activity {

    private static final String TAG = "AnimationStarter";
    ObjectAnimator textColorAnim;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.blinking_text_layout);

        Button startBlinkTextButton = (Button) findViewById(R.id.startBlinkTextButton);
        Button stopBlinkTextButton = (Button) findViewById(R.id.stopBlinkTextButton);
        final TextView blinkText = (TextView) findViewById(R.id.blinkTextView);

        startBlinkTextButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                textColorAnim = ObjectAnimator.ofInt(blinkText, "textColor", Color.BLACK, Color.TRANSPARENT); 
                textColorAnim.setDuration(1000); 
                textColorAnim.setEvaluator(new ArgbEvaluator());     
                textColorAnim.setRepeatCount(ValueAnimator.INFINITE); 
                textColorAnim.setRepeatMode(ValueAnimator.REVERSE); 
                textColorAnim.start();
            }
        });
        
        stopBlinkTextButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if(textColorAnim != null) {
                    textColorAnim.cancel();
                    blinkText.setTextColor(Color.BLACK);
                }
            }
        });

    }

}


Notice on "Stop Blinking Text" button press we are simply cancelling the current animation and setting the color back to black as the transparency of the text can be different as per the state in which the blinking animation was cancelled.

Note :
  • clearAnimation() method of View will have no effect on ObjectAnimator.
  • If you call start() on your ObjectAnimator instance n times then you will have to call cancel() n times for animation to completely stop.

 You can try out the code. Recorded video is as follows - 



Related Links

Creating bouncing ball Animation in Android

Background

In this post I am going to show a very simple animation - Bouncing a ball. As much as Animations are very cool to look at, they are tricky and must be handled carefully.

Animation coding Tip : Just a tip here. Animations are generally started in onResume() method and stopped in onPause() method. You should not do it in onCreate() and onDestroy() methods as these methods are not guaranteed to be invoked every time.


Creating the Layouts

Lets create layouts that we will need to create a animated bouncing ball. To start with lets first create our ball.

For this I am going to create an oval shape in android. This will be in ball_shape.xml file under drawable folder. Contents of it are - 

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval" >

    <solid android:color="#8c0000" />

    <stroke
        android:width="2dp"
        android:color="#fff" />
    
    <size
        android:height="80dp"
        android:width="80dp" />

</shape>

This is a simple circular shape with red color fill. We will use this as our ball. Now lets go ahead and create our actual layout with a button to animate this ball and of course the ball itself.

Put following content inside animation_layout.xml file under layout folder.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/bounceBallButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="Bounce Ball" />

    <ImageView
        android:id="@+id/bounceBallImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_below="@id/bounceBallButton"
        android:background="@drawable/ball_shape" />

</RelativeLayout>


As you can see we have a button and a ball (essentially ImageView with background set as oval shape) below it. Let's animate this now with our code. Layout will looks as follows -



Animating Bouncing Ball

To animate the ball we fill first set the layout of the Activity with the layout xml we have just created. Then we will get reference to our Button and ball and when user click on the button we will animate the ball so that it appears like bouncing.

Here is the code for it.

package com.osfg.animationdemo;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.BounceInterpolator;
import android.view.animation.TranslateAnimation;
import android.view.animation.Animation.AnimationListener;
import android.widget.Button;
import android.widget.ImageView;

public class AnimationStarter extends Activity {

    private static final String TAG = "AnimationStarter";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.animation_layout);

        Button bounceBallButton = (Button) findViewById(R.id.bounceBallButton);
        final ImageView bounceBallImage = (ImageView) findViewById(R.id.bounceBallImage);

        bounceBallButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                bounceBallImage.clearAnimation();
                TranslateAnimation transAnim = new TranslateAnimation(0, 0, 0,
                        getDisplayHeight()/2);
                transAnim.setStartOffset(500);
                transAnim.setDuration(3000);
                transAnim.setFillAfter(true);
                transAnim.setInterpolator(new BounceInterpolator());
                transAnim.setAnimationListener(new AnimationListener() {

                    @Override
                    public void onAnimationStart(Animation animation) {
                        Log.i(TAG, "Starting button dropdown animation");

                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        Log.i(TAG,
                                "Ending button dropdown animation. Clearing animation and setting layout");
                        bounceBallImage.clearAnimation();
                        final int left = bounceBallImage.getLeft();
                        final int top = bounceBallImage.getTop();
                        final int right = bounceBallImage.getRight();
                        final int bottom = bounceBallImage.getBottom();
                        bounceBallImage.layout(left, top, right, bottom);

                    }
                });
                bounceBallImage.startAnimation(transAnim);
            }
        });

    }

    private int getDisplayHeight() {
        return this.getResources().getDisplayMetrics().heightPixels;
    }
}


We have simply used Translate Animation with bounce interpolator so that our ball can be viewed as bouncing vertically .You can install and try out this code. You can see the recorded video below -






Related Links


Centering a button in android Linear and Relative Layouts

Background

I have tried centering various views in Android and each time I end by with incorrect layouts. So in this post I am going to cover how to center a simple button in your layout. I will show this for both layouts -
  1. Linear Layout and
  2. Relative Layout
Before we proceed to see how the actual layout files look like lets see the two layout view attributes that are commonly confused with -
  1. android:gravity and : Sets the gravity of the content of the View it's used on.
  2. android:layout_gravity  : Sets the gravity of the View or Layout relative to its parent.
So generally you can either put android:gravity="center" on the parent or android:layout_gravity="center" on the child.

Centering a Button in Linear Layout

For Linear layout you should use xml (button_linear.xml) that looks something like below - 


<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    android:orientation="vertical" >

    <Button
        android:id="@+id/centerButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

</LinearLayout>


This will place the button on the center of the screen. If you want to center it just vertically or horizontally you can use following values in  android:gravity tag - 
  • center_vertical|center_horizontal or center (For centering in whole screen)
  • center_vertical (For centering vertically)
  • center_horizontal (For centering horizontally)
and layout should look like



 Now let's see the same in a Relative layout.

Centering a Button in Relative Layout

In Relative Layout the xml would be

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/centerButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Hello World!" />

</RelativeLayout>

Notice the  android:layout_centerInParent attribute

This will put the button in the center of entire screen. Analogous to linear layout , attributes that can be used here are - 
  1. android:layout_centerInParent="true" (For centering in whole screen)
  2. android:layout_centerVertical="true" (For centering vertically)
  3. android:layout_centerHorizontal="true" (For centering vertically)
 Layouts will look same as the screenshots provided above for linear layout.

Related Links

Sunday, 26 April 2015

Using Fabric Python command-line tool

What is Fabric?

You can visit the fabric site . It gives the most apt description of what fabric is.

Fabric is a Python (2.5-2.7) library and command-line tool for streamlining the use of SSH for application deployment or systems administration tasks.

More specifically, Fabric is:

  • A tool that lets you execute arbitrary Python functions via the command line
  • A library of subroutines (built on top of a lower-level library) to make executing shell commands over SSH easy and Pythonic.

Prerequisites

  1. Assuming you have fair knowledge of python basics. If not please go over the basics in the tutorial - The Python Tutorial
  2. Also you mus have python installed. If not refer to the guide -  The Hitchhiker’s Guide to Python!
    1. Installing Python on Mac OS 
    2. Installing Python on Windows
    3. Installing Python on Linux 
Note : Fabric is supported only by Python versions (2.5-2.7).

Installing Fabric

 Before you install Fabric you need to install modules needed to install other modules. For that you can either install - 
  1. pip or
  2. setuptools
I am going to use pip to install fabric as it is the latest one. To install Fabric use the following command -


 pip install fabric

and your fabric should be installed.  You can see various related installation ways here. You can see the installed module in  
  • <Python installation directory>\Lib\site-packages .



For me it is located in 
  • C:\Python34\Lib\site-packages\fabric
You can see the fab. exe file in
  • C:\Python34\Scripts
which we have already added in the PATH environment variable [This is the same place where you have pip and easy_install executable]

Getting Started

Lets start with our usual "Hello World!"  example. Create a file called fabfile.py and add following content in it - 

def helloworld():
        """This is a test hello world fab method"""
        print("Hello World!")

To see list of available fabric commands do  - 
  • fab -l
For above file you should see something like - 

[athakur@localhost athakur]$ fab -l
Available commands:

    helloworld  This is a test hello world fab method

Next it's time to execute the command itself. Execute
  • fab helloworld
and you should see Hello World! printed on the console.

Note :  Any method that starts with an underscore (_) is a private method and cannot be used directly as fab command. It will even not be listed in fab -l command.

Consider following code -

def helloworld():
        """This is a test hello world fab method"""
        print("Hello World")
        _private_helloworld()

def _private_helloworld():
        """ This is private method and should not be listed with fab -l"""
        print("Private hello World")

Execute fab -l  and you should again see the same output as above i.e you should not see _private_helloworld method listed there.

Executing fab helloworld should print following now -

[athakur@localhost athakur]$ fab helloworld
Hello World
Private hello World
Done.

Note : The fab tool simply imports your fabfile and executes the function or functions you instruct it to. There’s nothing magic about it – anything you can do in a normal Python script can be done in a fabfile!

Fabfile discovery


Fabric is capable of loading Python modules (e.g. fabfile.py) or packages (e.g. a fabfile/ directory containing an __init__.py). By default, it looks for something named (to Python’s import machinery) fabfile - so either fabfile/ or fabfile.py.

The fabfile discovery algorithm searches in the invoking user’s current working directory or any parent directories. Thus, it is oriented around “project” use, where one keeps e.g. a fabfile.py at the root of a source code tree. Such a fabfile will then be discovered no matter where in the tree the user invokes fab.


Fabric Tasks with arguments

Put the following  content in fabfile.py

def helloworld(name="Aniket"):
        """This is a test hello world fab method. Syntax : fab helloworld:name=<your name>"""
        print("Hello World from %s!" %name)
        _private_helloworld()

def _private_helloworld():
        """ This is private method and should not be listed with fab -l"""
        print("Private hello World")

and run 
  • fab helloworld
You should get

[athakur@localhost athakur]$ fab helloworld
Hello World from Aniket!
Private hello World
Done.


Or you can execute by giving name argument as
  • fab helloworld:name="John" or simply
  • fab helloworld:"John"
and you should get output as

[athakur@localhost athakur]$ fab helloworld:"John"
Hello World from John!
Private hello World
Done.

Running fabric tasks on other machines

Replace your fabfile with following contents :

from fabric.api import run

def host_name():
        run('uname -a')

and then run it. You should br prompted for hostname and then password for the user you are already logged in as.

[athakur@localhost athakur]$ fab host_name
No hosts found. Please specify (single) host string for connection: localhost
[localhost] run: uname -a
[localhost] Login password for 'athakur':
[localhost] out: Linux localhost 2.6.32-504.8.1.el6.x86_64 #1 SMP Wed Jan 28 21:11:36 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

Done.
Disconnecting from localhost... done.

Troubleshooting

In Windows while installing Fabric you may get following error - 

building 'Crypto.Random.OSRNG.winrandom' extension
warning: GMP or MPIR library not found; Not building Crypto.PublicKey._fastmath
error: Microsoft Visual C++ 10.0 is required (Unable to find vcvarsall.bat).




If you get this you will have to install Microsoft Visual C++ compiler. See Stack overflow answers in the 1st link of related Sections. This is windows specific issue. If you are using Linux this should not occur.

Or You can install MinGW (Minimalist GNU for Windows) as I did. You need to install msys package under MinGW


 and add following entries in your PATH env variable.
  • C:\MinGW\bin
  • C:\MinGW\msys\1.0\bin [This is where you will find chmod executable]

Then run your command from normal windows command prompt.


Related Links

Sunday, 12 April 2015

Using Async Tasks in Android

Background

The whole android story behind this posts revolves around a single concept - the UI Thread. Lets understand what is this UI thread and what makes it so important. 

  • Each application has a main thread which is also called UI thread.
  • All the application components that are a part of same process will use this same UI thread. 
  •  All the android life cycle methods, the system callbacks, user interactions etc are handled by this UI thread.
Now you see why this main thread (UI Thread) is so important. You should avoid performing expensive time consuming operations on main thread as it will block your application altogether. This is one of the reasons why you may see ANR (App not responding) messages on you android device.

Note : Generally all components in an android application will run in same process unless you explicitly specify components to run in different processed in the manifest file.

So in this post we will see how to run your time consuming processes in Async task which basically runs your time consuming process in a new thread.

Why you should not do time consuming processing on UI Thread?

I am creating a simple that has a download button. To simulate a time consuming operation I am simply going to make the main thread sleep for 5 seconds.

My MainActivity code is as follows - 

package com.opensourceforgeeks.asynctaskdemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/**
 * @author athakur
 */
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button downloadButton = (Button) findViewById(R.id.download_button);
        downloadButton.setOnClickListener(new OnClickListener() {
           
            @Override
            public void onClick(View v) {
                try {
                    //sleep for 5 seconds
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}
 

After you install the app on your android device or emulator  click on download button. You should see the following screen - 



Note :  As usual I am skipping showing the resource code in the posts assuming you should be comfortable creating one now. If not you can always go back and see basic post -


So there you go. You got an ANR (App Not responding). This means your code is very bad and poor quality. Now lets see how we can make use of Async task to get rid of this ANR.

Using Aysnc Task for time consuming  processing

I am going to slightly change the code now. Will add a textView at the top which will show the download status - stop, progress and completed. 




Code is as follows - 


package com.opensourceforgeeks.asynctaskdemo;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
/**
 * @author athakur
 */
public class MainActivity extends Activity {

    Button downloadButton;
    TextView downloadStatus;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        downloadButton = (Button) findViewById(R.id.download_button);
        downloadStatus = (TextView) findViewById(R.id.downlaodStatus);
        downloadButton.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                new DownloadAsynctask().execute("TestInput");
            }
        });
    }
    
    class DownloadAsynctask extends AsyncTask<String, Integer, Boolean> {    
        @Override
        protected String doInBackground(String... params) {
            downloadStatus.setText(R.string.download_progress);
            try {
                //sleep for 5 seconds
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            downloadStatus.setText(R.string.download_completed);
            return null;
        }
        
    }
}

Ok Go ahead and install the app and click on the download button.



Opps! Your app would crash with following error.

04-12 16:05:51.241: E/AndroidRuntime(11317): FATAL EXCEPTION: AsyncTask #1
04-12 16:05:51.241: E/AndroidRuntime(11317): Process: com.opensourceforgeeks.asynctaskdemo, PID: 11317
04-12 16:05:51.241: E/AndroidRuntime(11317): java.lang.RuntimeException: An error occured while executing doInBackground()
....
04-12 16:05:51.241: E/AndroidRuntime(11317): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
....

But what happened here?

Note : Only the thread that created and rendered a View can alter it and that thread is main UI thread. As I mentioned before Async Task starts a new thread and doInBackground method essentially runs in that thread. So you cannot update any of the UI elements from this thread. You can only do that from UI thread.

Next natural question would be how will that be possible? Is there a callback? Well, there are. There are other methods in AsyncTask that we can override to leverage it. For example methods like onPreExecute(), onProgressUpdate() and onPostExecute() run in UI thread and can be used to update the UI elements.

So let us make that changes. Few changes that I am going to make in the upcoming code - 
  • Instead of making thread sleep for 5 seconds in one go I am going to make thread sleep 5 times each for 1 sec to show how onProgressUpdate() methods works.
  • I will override onPreExecute(), onProgressUpdate(), and onPostExecute()  to show how they work. Typically I will update the downloadStatus TextView that we had in above code with corresponding download status.
Code is as follows -

package com.opensourceforgeeks.asynctaskdemo;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
/**
 * @author athakur
 */
public class MainActivity extends Activity {

    Button downloadButton;
    TextView downloadStatus;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        downloadButton = (Button) findViewById(R.id.download_button);
        downloadStatus = (TextView) findViewById(R.id.downlaodStatus);
        downloadButton.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                new DownloadAsynctask().execute("TestInput");
            }
        });
    }
    
    class DownloadAsynctask extends AsyncTask<String, Integer, Boolean> {    

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            downloadStatus.setText(R.string.download_progress);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            downloadStatus.setText(getString(R.string.download_progress) + " : " + values[0] + "%");
        }

        @Override
        protected Boolean doInBackground(String... params) {
            
            //sleep for 5 seconds
            for (int i=0;i<5;i++) {
                try {
                    Thread.sleep(1000);
                    publishProgress((i+1)*20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    return false;
                }
            }

            return true;
        }
        

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            if(result) {
                downloadStatus.setText(R.string.download_completed);
            }
            else {
                downloadStatus.setText(R.string.download_incompleted);
            }
            
        }
        
    }
}


And as expected this time your application should not crash and you should see following set of screens on click of download button -





Note : Skipping few screenshots here. You should see update progress at 20%, 40%, 60% and 80%.


Few important points

  • Notices the generics in Aysnctask definition? -  class DownloadAsynctask extends AsyncTask<String, Integer, Boolean>. 
  • Here first generic argument String is the type of argument that you will give in execute() method when starting async task. We have used new DownloadAsynctask().execute("TestInput"); This is the argument that doInBackground() methods receives - protected Boolean doInBackground(String... params)
  • Next generic argument in Integer. It is basically what you would receive in 
    onProgressUpdate() method. The argument in this method will be array of generic value specified as 2nd generic argument. You can see protected void onProgressUpdate(Integer... values) 
  • Last we have Boolean. This is basically the value that 
    doInBackground() methods returns to onPostExecute() methods. You can see - return true; in the doInBackground method and protected void onPostExecute(Boolean result).
  •  doInBackground() may call publishProgress() as we have used above which will make a call back to onProgressUpdate() to update the progress of background thread.

Related Links

t> UA-39527780-1 back to top