Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deal with deprecated classes in Android to keep compatibility

I am getting back to work on an app I worked on a while ago, when I had everything built around Android 2.2 Froyo.

I have updated my SDK for the latest APIs and noticed that the ClipboardManager features I was using are deprecated. I updated the code to use the newer ClipData model and tried it out on my Froyo phone and, of course, I get a NoClassDefFoundError in the new code.

I've had a look around SO and haven't found any real discussions of general strategy for maintaining backwards compatibility.

I'm not entirely sure how I should handle this and other situations where the API differs, because I want users of all versions to be able to use my app.

Should I be doing a check as follows?

if(version == old){    use old API; } else {    use new API; } 

If so, I have deprecated code in my class and Eclipse will have the warning there forever.

On the other hand, I could just build against an old version of the API and hope that new versions will handle it okay. But then I run the risk of building against buggy or low-performance code when a better alternative is available.

What is the best way to deal with this?

like image 719
HXCaine Avatar asked Jun 12 '11 11:06

HXCaine


People also ask

What to do with deprecated methods in Android?

Compilers issue warnings when a deprecated program element is used or overridden in non-deprecated code. Use of the @Deprecated annotation on a local variable declaration or on a parameter declaration or a package declaration has no effect on the warnings issued by a compiler.

Is it OK to use deprecated methods Android?

Yes you can use deprecated methods as long as the depreciated method exists in the framework. By deprecating a method the platform developers are trying to tell you that either something is wrong with the method or there is already better way for doing the task.

Is it OK to use deprecated packages?

Essentially deprecated is a warning to you as a developer that while the method/class/whatever is there and works it is not the best way to do it. Either a newer and better alternative is available or (sometimes) there is something subtly broken about it that makes it not advisable to use.


2 Answers

You can do that (checking the API version).

You can also use reflection to call the newer classes.

I wouldn't worry about using deprecated methods as all Android versions are backwards compatible, saying that you want to watch when things are for 3.0 Honeycomb as these are a little different.

Here's an explanation of how to use reflection: (yes it's been on SO before, so maybe search for reflection)

http://www.youtube.com/watch?v=zNmohaZYvPw&feature=player_detailpage#t=2087s

I'm looking at making the project this is in available but until then here's some code:

(You could do this in a class that extends Application i.e. one time setup)

 public static Method getExternalFilesDir;      static {             try {                     Class<?> partypes[] = new Class[1];                     partypes[0] = String.class;                     getExternalFilesDir = Context.class.getMethod("getExternalFilesDir", partypes);             } catch (NoSuchMethodException e) {                     Log.e(TAG, "getExternalFilesDir isn't available in this devices api");             }     }  

Now getExternalFilesDir() is only available on API level 8 or above, so I want to use this if they have (Froyo), but otherwise I need another method.

Now I have my test for the method I can go ahead and attempt to use it:

  if(ClassThatExtendsApplication.getExternalFilesDir != null){             Object arglist[] = new Object[1];             arglist[0] = null;               File path = (File) ClassThatExtendsApplication.getExternalFilesDir.invoke(context, arglist);            // etc etc   } else {       // Not available do something else (like your deprecated methods / or load a different class / or notify they should get a newer version of Android to enhance your app ;-))   } 

Hope that helps and shortcuts a lot of googling :-)

P.S. if in the else you want to use your deprectated methods still, just add the @SuppressWarnings("deprecation") annotation above it, This will get rid of the warning and you have done it for the right reasons as you are using the latest API's when possible.

like image 198
Blundell Avatar answered Sep 24 '22 06:09

Blundell


Here is an example:

import android.os.Build;  public static int getWidth(Context mContext){     int width=0;     WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);     Display display = wm.getDefaultDisplay();      if(VERSION.SDK_INT > VERSION_CODES.HONEYCOMB){                            Point size = new Point();         display.getSize(size);         width = size.x;     }      else{          width = display.getWidth();  // deprecated, use only in Android OS<3.0.     }      return width; }  

as you can see the section of code:

  if(VERSION.SDK_INT > VERSION_CODES.HONEYCOMB){                                Point size = new Point();             display.getSize(size);             width = size.x;         }  

is only available for Android 3.0 and later versions, if you want this code available at least for Jelly Bean (Android 4.1) use:

  if(VERSION.SDK_INT > VERSION_CODES.JELLY_BEAN){                                Point size = new Point();             display.getSize(size);             width = size.x;         }  

VERSION.SDK_INT The user-visible SDK version of the framework; its possible values are defined in Build.VERSION_CODES.

More info about: Build.VERSION

And you can see the VERSION_CODES constats here: Build.VERSION_CODES

like image 45
Jorgesys Avatar answered Sep 23 '22 06:09

Jorgesys