To start off with, there are two ways to access the API level at runtime. They are
Build.VERSION.SDKand
Build.VERSION.SDK_INTBuild.VERSION.SDK returns a String and is accessible by all versions of Android, while Build.Version.SDK_INT returns an int and can be used by 4+.
The SDK versions of Android are
1 - Android 1.0
2 - Android 1.1
3 - Android 1.5 Cupcake
4 - Android 1.6 Donut
5 - Android 2.0 Eclair
6 - Android 2.0.1 still Eclair
7 - Android 2.1 also still Eclair
8 - Android 2.2 Froyo
9 - Android 2.3 Gingerbread
SDK 1, 2, 5 and 6 are considered obsolete and combined represent less than 0.1% of the user base.
If you are ensuring compatibility with Android 1.5, simply use
Integer.parseInt(Build.VERSION.SDK)to obtain the value as an integer.
Now, in the example for this tutorial we will make a View subclass and attempt to detect touches with it. The ability to detect multiple touches simultaneously was introduced in Android 2.0 (SDK 5) so we will be detecting only single point touches when the application is run on Cupcake and Donut and will detect multiple points when run on Eclair and above.
First create your project for using the Cupcake SDK. Create a new class and extend View and implement OnTouchListener. It should start off like this:
The OnTouchListener interface gives us access to the onTouch(View v, MotionEvent e) method. This will be called anytime the user touches the screen. The instance of MotionEvent contains all the information we need about how the user touched the screen.
package com.andylanddev.reflectiontest;
import android.content.Context;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;
public class CustomView extends View implements OnTouchListener{public CustomView(Context context) {super(context);}
@Overridepublic boolean onTouch(View v, MotionEvent event) {return false;}}
There are three principal methods of MotionEvent in Eclair+ that allow the detection of multiple touches. The first is getPointerCoint() which simply returns the number of places the user has touched the screen. The second and third are getX(int pointerNumber) and getY(int pointerNumber). These allow you to get the value of each pointer independently. In order to access these methods, we will use reflection. First, declare the instances of the each Method above your header.
private Method getPointerCount, getX, getY;Now, instantiate the methods in your constructor.
The class class contains an instance method called getMethod(String methodName, params...). By calling this on MotionEvent.class we can retrieve the methods without calling them directly. The params... is for a comma separated list of all the method's parameters' class names. A NoSuchMethodException will be thrown if these methods do exist (such as in Cupcake and Donut) so we catch the exception, but ignore it and move on.
try{getPointerCount = MotionEvent.class.getMethod("getPointerCount");getX = MotionEvent.class.getMethod("getX",Integer.TYPE);getY = MotionEvent.class.getMethod("getY",Integer.TYPE);}catch(NoSuchMethodException e){}
Now, add the following code to your onTouch method.
The first thing we do is pull the SDK number and create ArrayLists to hold the values we collect. In the first part of the if, we grab down the coordinates for each pointer. The invoke(Object, params..) is as if you were calling object.(params...) in the normal way. The else statement is called for Donut and Cupcake and grabs the single pointer data in the normal fashion. For simplicity, we just spit out the data in Logcat to see what's going on.
String sdk = Build.VERSION.SDK;//Declare arrays to store coordinate dataArrayList<String> outputValues = new ArrayList<String>();//If user is on Eclair or higherif(Integer.parseInt(sdk) > 4){try{//Get pointer countint pointerCount = (Integer)getPointerCount.invoke(event);//Add the values to the arrays
for(Integer i = 0; i < pointerCount; i++){outputValues.add("Pointer " + i + ": " +(Float)getX.invoke(event, i) + "," +(Float)getY.invoke(event, i));}//invoke throws multiple exceptions so for convenience//we handle them generically}catch(Exception e){}//If on an Archaic version of Android}else{//Add the one pointer we can getxCoord.add(event.getX());yCoord.add(event.getY());}//Spit out a log of our findingsfor(Integer i = 0; i < xCoord.size(); i++){Log.e(sdk, outputValues.get(i));}
No comments:
Post a Comment