Search code examples
androidandroid-sensorsaltitude

Android: How do I call a method which is existing in other API Level?


I have application using Android 2.1 which utilize LocationManager to get the altitude. But now, I need to obtain the altitude using SensorManager which requires API Level 9 (2.3).

How can I put the SensorManager.getAltitude(float, float) in my 2.1 android application by putting a condition and calling it by a function name (possible in normal Java)?

Thank you in advance

UPDATE 1 If you have noticed that my application need to be compiled using Android 2.1. That's why I'm looking for a way to call the function by name or in any other way that can be compiled.


Solution

  • You can call the method using reflection and fail gracefully in case of errors (like missing class or methods). See java.lang.reflect

    Other option is to compile code in level 9 but surround with try/catch to catch errors that would arise from execution on lower level. It could be fairly error prone, though, and I'd think twice about doing it.


    Update

    Here is test code

    public void onCreate(Bundle savedInstanceState)
    {
        try {
            // First we try reflection approach.
            // Expected result
            //    in 2.3 we print some value in log but no exception
            //    in 2.2 we print NoSuchMethodException
            // In both levels we get our screen displayed after catch
            Method m = SensorManager.class.getMethod("getAltitude",Float.TYPE, Float.TYPE);
            Float a = (Float)m.invoke(null, 0.0f, 0.0f);
            Log.w("test","Result 1: " + a);
        } catch (Throwable e) {
            Log.e("test", "error 1",e);
        }
    
        try {
            // Now we try compiling against 2.3
            // Expected result
            //    in 2.3 we print some value in log but no exception
            //    in 2.2 we print NoSuchMethodError (Note that it is an error not exception but it's still caught)
            // In both levels we get our screen displayed after catch
            float b = SensorManager.getAltitude(0.0f, 0.0f);
            Log.w("test","Result 2: " + b);
    
        } catch (Throwable e) {
            Log.e("test", "error 2",e);
        }
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    

    Results:

    2.3

    09-14 07:04:50.374: DEBUG/dalvikvm(589): Debugger has detached; object registry had 1 entries
    09-14 07:04:50.924: WARN/test(597): Result 1: NaN
    09-14 07:04:51.014: WARN/test(597): Result 2: NaN
    09-14 07:04:51.384: INFO/ActivityManager(75): Displayed com.example/.MyActivity: +1s65ms
    

    2.2

    09-14 07:05:48.220: INFO/dalvikvm(382): Could not find method android.hardware.SensorManager.getAltitude, referenced from method com.example.MyActivity.onCreate
    09-14 07:05:48.220: WARN/dalvikvm(382): VFY: unable to resolve static method 2: Landroid/hardware/SensorManager;.getAltitude (FF)F
    09-14 07:05:48.220: DEBUG/dalvikvm(382): VFY: replacing opcode 0x71 at 0x0049
    09-14 07:05:48.220: DEBUG/dalvikvm(382): VFY: dead code 0x004c-0064 in Lcom/example/MyActivity;.onCreate (Landroid/os/Bundle;)V
    09-14 07:05:48.300: ERROR/test(382): error 1
            java.lang.NoSuchMethodException: getAltitude
            at java.lang.ClassCache.findMethodByName(ClassCache.java:308)
    

    Skipped stack trace

    09-14 07:05:48.300: ERROR/test(382): error 2
        java.lang.NoSuchMethodError: android.hardware.SensorManager.getAltitude
        at com.example.MyActivity.onCreate(MyActivity.java:35)
    

    Skipped more stack trace

    09-14 07:05:48.330: DEBUG/dalvikvm(33): GC_EXPLICIT freed 2 objects / 64 bytes in 180ms
    09-14 07:05:48.520: INFO/ActivityManager(59): Displayed activity com.example/.MyActivity: 740 ms (total 740 ms)