- 1 API Overview
- 2 Dates and Times
- 3 2D Graphics Concepts
- 4 2D Versus 3D Graphics
Here is an overview of some of the most important package namespaces and classes in the Android API.
- android.content.Context is the base class for android.app.Activity and other similar classes. Here you will find important methods for accessing application package data and the application environment.
- android.view.View is the base class for all widgets. The android.view namespace defines non-widget-specific utility classes.
- android.widget is the namespace where you will find specific widget implementations and related classes.
- android.graphics is the namespace for the 2D graphics API; Canvas is the drawing context, Paint specifies settings like what colour, drawing mode, text settings etc to use, and Typeface is how you specify fonts.
- android.content.Intent is the basic IPC mechanism.
- android.os contains various useful classes to do with the UI framework: Handler for feeding tasks/messages to a Looper, and AsyncTask for running tasks on background threads that need coordination with the UI. Here you will also find Parcel and Bundle, which are different ways of serializing/deserializing data, mainly meant to be used for saving/restoring UI state.
New versions of Android introduce new capabilities, and sometimes drop support for old ones. Each version of Android has an associated API level, and each app in its manifest declares its “minimum” and “target” SDK version (i.e. API level). The minimum API level indicates that it will not work (or at least has not been tested) with any older Android version, and will likely crash. The target API level is used to adjust some automatic behaviour of the Android system, to match with expectations of the app.
Dates and Times
Java (and Android) offer a confusing plethora of different classes to do with dates and times. This section will try to shed some clarity on the thicket.
- java.util.GregorianCalendar — this is the main class to be used for constructing and manipulating dates and times. Note that many important methods come from its java.util.Calendar superclass.
- java.util.TimeZone — gives you information about the current system time zone as well as other available time zones that the system knows about.
- java.util.Date — this remains an essential class, even though most of its constructors and methods are deprecated. You can obtain one of these from a Calendar object by calling its getTime method. The only reason you need objects of this class is because the formatting routines don’t work with Calendar objects!
- java.text.DateFormat — this is where you will find the functions for doing locale-dependent date formatting. Note they only work on Date objects, not Calendar or GregorianCalendar objects.
- android.text.format.DateFormat — convenience routines for obtaining suitable java.text.DateFormat objects for the user’s current locale/format settings. Also lets you format dates according to custom formats.
- java.text.SimpleDateFormat — lets you create custom date formats.
- java.util.SimpleTimeZone — not sure what the point of this is. Why would you want to define your own time zones?
2D Graphics Concepts
Overview of the Android 2D graphics API.
A Canvas provides the basic drawing context. On-screen drawing of most widgets is done in their override of View.onDraw, which gets passed a Canvas into which they render their display. Alternatively, if you want to do drawing at times dictated by your app, rather than by the system, then you can use a SurfaceView.
You can also create your own Canvas objects to do off-screen rendering. You do this by wrapping them around a Bitmap object that you set up.
The normal Canvas coordinate system has the X-coordinate increasing from left to right, and the Y-coordinate increasing from top to bottom, with (0, 0) at the top-left of the drawing area. However, you can alter this by transforming drawing through a Matrix.
A Bitmap is the container for an array of pixels. You can either supply the pixels (in which case the Bitmap is immutable—i.e. the graphics API will not draw into them), or have the graphics API allocate the space for them itself (in which case the Bitmap is mutable—can be drawn into). In the latter case, you must remember to call the recycle method when you have finished with the Bitmap; contrary to the documentation saying “This is an advanced call, and normally need not be called”, you will be quite likely to hit “out of memory” errors if you create lots of mutable bitmaps without doing this.
Pixel colours are specified in many places as a 32-bit integer with alpha, red, blue and green components each taking up 8 bits. Assuming that “alpha”, “red”, “blue” and “green” are each integers in the range 0 .. 255, you can build them into a colour value as follows:
int color = alpha << 24 | red << 16 | green << 8 | blue;
A Paint object contains various settings used to control drawing of some object into a Canvas: the colour to use, what transfer modes and filtering effects to apply, Path-rendering settings, and text settings.
A Typeface is how you specify a font. Note that there is only a limited set of preinstalled system fonts, with no (official) provision for adding more. If you want more fonts, you will have to include them with your app, or access them from a user download area, or something.
A Path is the representation of a scalable geometric object. This could be as simple as a single circle, oval or rectangle, or it could be more complicated and consist of multiple segments made out of cubic and quadratic Bézier curves and straight-line segments. A path can be filled or stroked. It can also be used for clipping drawing in a Canvas.
Note that there is no equivalent to the PostScript pathforall operator: there is no way to read back the components of the definition of a Path. If you need to maintain this information, you will need to define your own geometry object, which will convert its contents to a Path on demand.
A Shader gives you more advanced options for drawing with a Paint. By default a paint renders an area of a single flat colour, but setting the right kind of Shader gives you options for applying gradient fills, filling with a bitmap image, and combinations of these.
Why Do My Graphics Look So Jaggy?
The graphics API includes options for anti-aliasing, but these are not enabled by default (why not? performance issues on older hardware?). To make things look good, use Paint.setAntiAlias for rendering smooth geometry, and Paint.setFilterBitmap for smooth scaling of bitmaps.
The video Android Graphics and Animations presented by Romain Guy and Chet Haase at the Devoxx 2010 Java conference gives an overview of the graphics API and how to do animations.
2D Versus 3D Graphics
Android uses quite different APIs for 2D versus 3D graphics. The 2D graphics API is built on the Skia graphics library that Google acquired along with the company that created it. The 3D graphics API is OpenGL-ES, the “embeddable” subset of the well-known cross-platform OpenGL 3D graphics API.
The 2D graphics engine is completely integrated into the UI, and is used for all on-screen drawing of windows, widgets etc. For example, to create your own custom widget, it is easy enough to subclass View, do whatever custom rendering you want in its onDraw method and event handling in onTouchEvent.
3D graphics is not quite so seamlessly integrated. The easiest way to do an on-screen 3D display is to subclass GLSurfaceView, in addition to which you need to provide a custom subclass of GLSurfaceView.Renderer which does the actual setup and drawing.
A GLSurfaceView offers two “render modes”, selected by calling setRenderMode: RENDERMODE_CONTINUOUSLY in which your Renderer is continually called to render the scene (the default), and RENDERMODE_WHEN_DIRTY where your Renderer is only invoked when you do a requestRender. Note this is quite different from normal 2D widgets, which are only (re)drawn in response to an invalidate call.
Note the difference in coordinate systems: in the 2D graphics API, y-coordinates increase downwards, while in OpenGL they increase upwards.
The available graphics primitives are more limited in 3D. Whereas in 2D you have complex entities like text, Paths, Drawables and Pictures, in 3D you just have points, lines and triangles. In particular, all object surfaces must be constructed out of triangles; curved surfaces are approximated to a limited extent by subdividing into smaller triangles, but more importantly by enabling smooth shading, which fools the eye into seeing continuous gradations instead of angular facets.
It is possible to use 2D graphics in 3D, by rendering a 2D image to a Bitmap, which is then used as a texture on an object surface in 3D.
Also note that OpenGL is strictly an on-screen real-time rendering API: it defines no “file format” for storing scenes/models in persistent storage, and it doesn’t support CPU-intensive functions like ray-tracing, radiosity and the like.
OpenGL-ES Versus Regular OpenGL
OpenGL-ES leaves out various capabilities of OpenGL which were deemed to have too high an overhead of implementation in an embedded environment. OpenGL-ES 1.1 is based on OpenGL 1.5, among the differences being:
- No Begin/End grouping and associated calls for individually specifying vertex info: instead, you must use the xxxPointer calls to pass entire buffers of coordinates at a time, and then draw them with DrawArrays (selecting contiguous subarrays) or DrawElements (selecting individual array elements by index).
- Only 2D textures, no 3D or 1D.
- No support for polygons other than triangles.
- ES adds the option to specify coordinates etc as fixed-point values (calls with an x suffix) instead of floating-point (f suffix).
android.opengl Versus khronos.opengles
Android provides two alternative styles of OpenGL API calls: the khronos.opengles calls are method calls off explicit GL objects, whereas the android.opengl calls are all static, and implicitly refer to a current GL context.
It looks like the latter are now the preferred form, since the addition of support for OpenGL-ES 2.0 in API level 8 (Android 2.2) was done only in the android.opengl style, not the khronos.opengles style.
OpenGL-ES 1.x Versus 2.0
Android 2.2 introduced support for OpenGL-ES 2.0, which is not backward-compatible with OpenGL-ES 1.1 or 1.0. However, the OpenGL-ES 1.x APIs remain available for existing code. When you write new code, you have to decide which one to use.
The main difference is that OpenGL-ES 2.0 drops support for the fixed-function pipeline. That is, all the traditional OpenGL material, lighting and matrix functions are no longer available (these are deprecated in more recent versions of regular OpenGL, too). In their place, you write custom vertex shaders and fragment shaders which give you total control over how your materials, lighting and transformations will work.
EGL is an API for giving direct control over creation of OpenGL contexts that render to on-screen windows, offscreen pixmaps, or additional graphics-card memory. GLSurfaceView provides a simple wrapper to save you using it directly, but you can still do so in cases where this isn’t flexible enough (like when you want to do offscreen rendering).
Documentation on OpenGL, OpenGL-ES and EGL can be found at khronos.org.