Using Animations and Creating Custom Animations for Android
September 25th, 2010
Using animations in your Android applications can help create an interesting and engaging experience for your users. They can be used in games and applications in a number of ways either as a visual treat or as a method to convey information. Fortunately Android has an animation framework that allows you to easily translate, rotate, scale and alter the alpha of (or a combination) a View. Common transitions like fade in/out or slide in from off screen are examples of animations the framework can produce.
Animations and Interpolators
The process of animating a View makes use of two classes the Animation and Interpolator classes. The Animation class describes various aspects of the animation such as the transformation (changes in position, alpha, etc) and the duration of the animation.
The Interpolator class describes the rate of change of the animation, for example a ScaleAnimation with an AccelerateIterpolator results in a View that scales slowly at first and speeds up until the end of the animation. There are a number of different interpolators the most basic LinearInterpolator to more complex ones such as AccelerateInterpolator, AccelerateDecelerateInterpolter and OvershootInterpolator.
Adding Animation to a View
Here is res/layout/main.xml, it contains a button called ‘butt’ that is centred in the screen.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/butt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Shake!"/> </RelativeLayout>Now we define our animation, res/anim/exampe_anim.xml , which is going to slide the button in from the bottom of the screen to the centre of the screen scaling from 0.5 to 1 as it travels all in 1.5 seconds. The p in 50%p means parent, since the Button is a primary child of the RelativeLayout this means 50% of the screen height.
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator" android:shareInterpolator="true"> <translate android:fromYDelta="50%p" android:toYDelta="0" android:duration="1500" /> <scale android:fromYScale="0.5" android:toYScale="1" android:fromXScale="0.5" android:toXScale="1" android:duration="1500" /> </set>To start the animation use AnimationUtils.loadAnimation(context, resID) to load the animation and the startAnimation(animation) method of the View class.
butt.startAnimation(AnimationUtils.loadAnimation(getBaseContext(), R.anim.example_anim));Read more: Creating Custom Animations
Android GPS Example
April 11th, 2010
For some reason there doesn’t seem to be a clear example showing how to use GPS on Android. Here is some code I have written that listens for location changes and displays the data in a TextView. The example also shows how to open the GPS setting with code via an Intent, since sometimes the GPS will be turned off by the user.
Code
package uk.co.hejp.GPSExample;
import android.app.Activity;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
public class Main extends Activity implements LocationListener {
/* this class implements LocationListener, which listens for both
* changes in the location of the device and changes in the status
* of the GPS system.
* */
static final String tag = "Main"; // for Log
TextView txtInfo;
LocationManager lm;
StringBuilder sb;
int noOfFixes = 0;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/* get TextView to display the GPS data */
txtInfo = (TextView) findViewById(R.id.textInfo);
/* the location manager is the most vital part it allows access
* to location and GPS status services */
lm = (LocationManager) getSystemService(LOCATION_SERVICE);
}
@Override
protected void onResume() {
/*
* onResume is is always called after onStart, even if the app hasn't been
* paused
*
* add location listener and request updates every 1000ms or 10m
*/
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10f, this);
super.onResume();
}
@Override
protected void onPause() {
/* GPS, as it turns out, consumes battery like crazy */
lm.removeUpdates(this);
super.onPause();
}
@Override
public void onLocationChanged(Location location) {
Log.v(tag, "Location Changed");
sb = new StringBuilder(512);
noOfFixes++;
/* display some of the data in the TextView */
sb.append("No. of Fixes: ");
sb.append(noOfFixes);
sb.append('\n');
sb.append('\n');
sb.append("Londitude: ");
sb.append(location.getLongitude());
sb.append('\n');
sb.append("Latitude: ");
sb.append(location.getLatitude());
sb.append('\n');
sb.append("Altitiude: ");
sb.append(location.getAltitude());
sb.append('\n');
sb.append("Accuracy: ");
sb.append(location.getAccuracy());
sb.append('\n');
sb.append("Timestamp: ");
sb.append(location.getTime());
sb.append('\n');
txtInfo.setText(sb.toString());
}
@Override
public void onProviderDisabled(String provider) {
/* this is called if/when the GPS is disabled in settings */
Log.v(tag, "Disabled");
/* bring up the GPS settings */
Intent intent = new Intent(
android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
@Override
public void onProviderEnabled(String provider) {
Log.v(tag, "Enabled");
Toast.makeText(this, "GPS Enabled", Toast.LENGTH_SHORT).show();
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
/* This is called when the GPS status alters */
switch (status) {
case LocationProvider.OUT_OF_SERVICE:
Log.v(tag, "Status Changed: Out of Service");
Toast.makeText(this, "Status Changed: Out of Service",
Toast.LENGTH_SHORT).show();
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
Log.v(tag, "Status Changed: Temporarily Unavailable");
Toast.makeText(this, "Status Changed: Temporarily Unavailable",
Toast.LENGTH_SHORT).show();
break;
case LocationProvider.AVAILABLE:
Log.v(tag, "Status Changed: Available");
Toast.makeText(this, "Status Changed: Available",
Toast.LENGTH_SHORT).show();
break;
}
}
@Override
protected void onStop() {
/* may as well just finish since saving the state is not important for this toy app */
finish();
super.onStop();
}
}
Permissions
Of course the Android framework has security permissions to protect the user. To get the permission to use GPS add a uses-permission tag with attribute android:name set to “android.permission.ACCESS_FINE_LOCATION” to the AndroidManifest.xml document as a direct child of the manifest tag, i.e:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />Notes When testing this code in the emulator, you can send mock fixes by connecting to the emulator using telnet, i.e. ‘telnet localhost 5554′ and typing: geo fix -10.223, 40.549
Playground: HEJP ColourPicker
February 3rd, 2010
Just been messing around with the Robot class, which is designed for automated testing of applications but has other uses. Here I have used it to write an application to get the pixel colour of any pixel on the screen. The GUI consists of a Canvas magnifying the area around the mouse pointer and a text field to display the pixel hex value.
How to Use
Move the mouse pointer to the pixel you’d like to know the colour of and hit Enter.
Source and Jar
Source (zip)
Jar
Notes Regarding the Robot Class
getColorPixel is very slow as I found out as soon as using it, the solution is to use createScreenCapture to get the pixels around the mouse pointer then read the colours from the BufferedImage.
How to Use
Move the mouse pointer to the pixel you’d like to know the colour of and hit Enter.
Source and Jar
Source (zip)
Jar
Notes Regarding the Robot Class
getColorPixel is very slow as I found out as soon as using it, the solution is to use createScreenCapture to get the pixels around the mouse pointer then read the colours from the BufferedImage.
Java Socket Programming, Handling Multiple Clients
October 17th, 2009
package uk.co.hejp.Server;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
public class ClientHandler implements Runnable {
Socket socket;
PrintStream out;
ClientHandler(Socket s) {
socket = s;
}
@Override
public void run() {
try {
out = new PrintStream(socket.getOutputStream());
} catch (IOException e) {
System.out.println("PrintStream Error");
}
out.println("Hello");
try {
socket.close();
} catch (IOException e) {
System.out.println("Failed to close, oddly...");
}
}
}
This particular implementation of ClientHandler just writes ‘Hello’ to the Socket and close()s.
And just for completeness here is an implementation of a Server that uses ClientHandler:
package uk.co.hejp.Server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
static ServerSocket socket;
static int port = 7999;
public static void main(String[] args) {
try {
socket = new ServerSocket(port);
System.out.println("Bound to port: " + port);
} catch (IOException e) {
System.out.println("Cannot bind to port: " + port);
System.exit(0);
}
while (true) {
try {
Socket s = socket.accept();
System.out.println("New Client: "+s.getInetAddress().toString());
(new Thread(new ClientHandler(s))).start();
} catch (IOException e) {
System.out.println("Failed to accept client");
}
}
}
}
To test this Server you can use telnet (telnet 127.0.0.1 7999) or in your favourite browser goto ‘http://localhost:7999/’ the result should be just a line to text ‘Hello’ assuming you have the Server running.