9

In Android I get the version of the SDK easily (Build.VERSION.SDK) but I need to use LabeledIntent only if the platform is newer than 1.6 (>Build.VERSION_CODES.DONUT)

I suppose that Reflection is necessary (I have read this link but it is not clear for a class or to me).

This is the code but it gives me an exception because in my Android 1.6, the compiler verifies if the package exists even if the condition is not applied:

 Intent theIntent=....;
      if(Integer.parseInt(Build.VERSION.SDK) > Build.VERSION_CODES.DONUT)
   {    
 try{
             Intent intentChooser = Intent.createChooser(intent,"Choose between these programs");
              Parcelable[] parcelable = new Parcelable[1];
              parcelable[0] = new android.content.pm.LabeledIntent(theIntent, "", "Texto plano", 0);
               intentChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, parcelable); 
  activity.startActivity(intentChooser);
   }
   catch(Exception e)
   {
    activity.startActivity(theIntent);
   }

  } else
  {
   activity.startActivity(intentMedicamento);
  }

HOW I SOLVED IT, SOME NOTES TO THE RIGHT ANSWER

@Commonsware show me the way to do it. We create a bridge class so that depending on the API LEVEL, you instance one class that uses an API LEVEL or another class that uses another API LEVEL. The only detail one beginner could forget is that you have to compile your app with the newest SDK you are goint to make reference.

public abstract class LabeledIntentBridge {
 public abstract Intent BuildLabeledIntent(String URL, Intent theintent);

 public static final LabeledIntentBridge INSTANCE=buildBridge();

 private static LabeledIntentBridge buildBridge() {
  int sdk=new Integer(Build.VERSION.SDK).intValue();

  if (sdk<5) {
   return(new LabeledIntentOld());
  }

  return(new LabeledIntentNew());
 }
}

So in the LabeledIntentNew, I included all the code that refers to LabeledIntent only available in API LEVEL 5. In LabeledIntentOld, I can implement another kind of control, in my case I return the intent itself without doing nothing more.

The call to this class is done like this:

LabeledIntentBridge.INSTANCE.BuildLabeledIntent(URLtest,theIntent);
netadictos
  • 7,602
  • 2
  • 42
  • 69
  • Which framework version are you using in you project? – Flo Nov 25 '10 at 13:17
  • @Flo.- My AndroidManifest defines minSdkVersion="4". LabeledIntent is only included in the SDK from API LEVEL 5 on. – netadictos Nov 25 '10 at 13:34
  • Yes but which framework version are actually using in your project? minSdkVersion is just meta information in the manifest file. When you created your project you should have selected a framework version in the creation dialog. – Flo Nov 25 '10 at 13:40
  • @Flo.- I change between 2.2 and 1.6, my app must be compatible with both. – netadictos Nov 25 '10 at 14:01
  • Ok, then of course when you switch back to 1.6 the compiler will throw an error cause the classes you trying to use are not in Android 1.6 framework. As you already said you'll have to use reflection, like mentioned in the blog post you linked to. – Flo Nov 25 '10 at 14:46

2 Answers2

2

Follow the wrapper class pattern documented in the page you linked to above.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I don't see clearly. In the link they use the method Debug.class.getMethod(),which would be the method to retrieve the LabeledIntent class? Thx for providing some code. – netadictos Nov 26 '10 at 07:48
  • @netadictos: Check out https://github.com/commonsguy/cw-advandroid/tree/master/Contacts/Spinners/ for another approach on the problem. – CommonsWare Nov 26 '10 at 12:51
  • it can help me in another way the way you create spinners, but to make compatible the code you indicate me does not compile for 1.6, because when I use the Android 1.6, it doesn't recognise the class android.provider.ContactsContract. Must it be compile for 2.2 and it works on 1.6 phones? – netadictos Nov 30 '10 at 11:48
  • thx so much, finally I imitated your code, I suppose that there is no problem to execute a package that makes reference to newer api classes whenever they reside in a class not instanced. I annotate what I do in my answer. It is good to make clear (for beginner level) that you have to compile with the newer SDK because it will not compile otherwise. – netadictos Nov 30 '10 at 12:24
1

You have to use reflection... The idea is good, but in your code you refer to LabeledIntent which is not available in 1.6. So when your app runs against 1.6 devices, it cannot find the class and crashes.

So the idea is to write code where you don't refer to LabeledIntent when running in 1.6. To do this, you can write a wrapper class (LabeledIntentWrapper) which extends LabeledIntent and call it in your function. So, in 1.6, the device will see a reference to a known class: LabeledIntentWrapper.

  • the problem is you use the reference to LabeledIntent anyway. That's why I mention reflection, it's essential, but really I don't know how to implement it because it has parameters. – netadictos Nov 26 '10 at 07:46