2010-12-29 20 views
19

Tener acceso a los contactos en Android android.jar para las versiones 1.6 tiene People.CONTENT_URI para invocar la información relacionada con los contactos, mientras que en las versiones posteriores necesitamos tener una API compatible con RawContacts.CONTENT_URI.¿Cómo admitir múltiples versiones de Android en tu código?

Lo mismo ocurre con el acceso al calendario, por ejemplo, ya que su URI se cambia en android 2.2.

¿Existe una mejor práctica para administrar todos los cambios diferentes sin agregar aplicaciones adicionales o compilar por separado para cada versión de los cambios?

Respuesta

3

Bastante Honestamente, es un dolor.

Normalmente, solo aíslo partes del código que son diferentes y acceden a ellas usando clases abstractas. Entonces, técnicamente creo una versión diferente para diferentes sistemas operativos.

Pero hay otras formas. El mejor que he visto involucra el uso de la reflexión.

+0

sí, está más cerca del problema específico de acceder a los contactos. Tal vez sea necesario crear un código similar para los datos adicionales que mantienen los cambios en la uri en versiones como el calendario – dhaval

0

La mejor práctica (aunque no para Android, pero para J2ME) que yo sepa, es el uso de pre-procesamiento C/C++ declaraciones labrados, como:

//#if S40 
    ... 
//#else 
    ... 
//#endif 

el apoyo de algunos IDE este tipo de procesamiento previo, por ejemplo, Netbeans. Que yo sepa, Eclipse tiene algunos complementos que también permiten el preprocesamiento. Realmente no sé si son aplicables al desarrollo de Android. Intenta googleear.

+0

¿Y cómo resolvemos para la inclusión de android.jar múltiple? – dhaval

+0

Netbeans admite inclusiones de múltiples jar según la clave de configuración, que de hecho se usa como preprocesador #define. Hay malas noticias: Netbeans no es compatible con Android :) Por otro lado, hay un complemento de Android para Netbeans llamado nbandroid: estaba en fase beta profunda (1/2 año atrás, probablemente smth ha cambiado) – barmaley

1

Hay un buen artículo sobre android.com al respecto: http://developer.android.com/resources/articles/backward-compatibility.html

Personalmente me gustaría sugerir la solución de clase de contenedor o una biblioteca envoltorio. Pero en casos pequeños, la reflexión debería estar bien (y en caso de que el rendimiento no sea un problema para usted).

Si necesita más información, pregunte en los comentarios.

+0

Desafortunadamente, el enlace está inactivo :) ¿Es este: http://developer.android.com/training/search/backward- compat.html? –

8

Hay muchos recursos que puede utilizar para ayudar a soportar múltiples versiones de Android.

  1. Leer esta entrada del blog here y continuación, lea éste here, que le ayudará a abordar nivel de la API problemas de soporte de versiones.
  2. Lea this Publicación de blog en soporte de pantalla múltiple , especialmente cómo la jerarquía de activos analizada en la carpeta res . Esto le ayudará comprender y diseñar cómo hacer estructura de carpetas de activos para admitir diferentes tamaños de pantalla/densidades y versiones de Android.
  3. Por último, escriba sus propios scripts personalizados de compilación para que pueda compilar con todas las versiones de android.
2
  • Si realmente no necesita las nuevas funcionalidades, y realmente tienen que apoyar viejas versiones de Android, lo deje caer. Crea tu aplicación para la versión más antigua y no te molestes con este tipo de cosas.
  • En el otro caso, puede detectar la versión usando Build, y usar el reflejo para cargar las clases que necesita.Un ejemplo de ello se puede encontrar en el source code of the K9Mail app
1

This is a great article para cuando se tiene que hacer la reflexión en Android (para soportar múltiples niveles de la API).

Y cuando debe tener recursos diferentes para diferentes niveles de API, this is the reference to use (consulte la sección sobre "Versión de plataforma (nivel de API)").

+0

Gran respuesta. Esto era justo lo que estaba buscando. –

1

Si en Eclipse, desde ADT versión 17 puede especificar el código para ejecutar con alguna versión simplemente como se describe en Lint API Check. La palabra de código es @TargetAPI (XX)

creo que sirve

13

Para mi dinero, una muy buena respuesta está al http://android-developers.blogspot.co.uk/2010/07/how-to-have-your-cupcake-and-eat-it-too.html. Sin embargo, el ejemplo es un poco más complicado de lo necesario, por lo tanto, basado en eso, aquí hay un ejemplo de cómo lidiar con él cuando se crean notificaciones. El motivo subyacente de esto funciona es la forma en que los motores Java interpretan las clases: solo las ve cuando es necesario, así que si envuelve el código específico de la versión en una clase y solo lo crea cuando sabe que está usando esa versión, todo funciona ...

Hay, por lo que puedo decir, dos generaciones de enfoques para crear notificaciones, y un cambio de nombres en el camino en el segundo. Entonces eso da tres formas de hacerlo. Para cada modo, crear una clase con la generación de notificación en ella:

El primer enfoque (utilizado a través de pan de jengibre):

public class MyNotificationBuilderToGingerBread { 
Notification notification = null; 

MyNotificationBuilderToGingerBread(Context myContext, int icon, String ticker, String title, String info, Long timeStamp, PendingIntent pendingIntent, int flags) { 
    notification = new Notification(R.drawable.ic_sb, ticker, timeStamp); 
    notification.setLatestEventInfo(myContext, title, info, pendingIntent); 
    notification.flags |= flags;   
} 

Notification get() { 
    return notification; 
} 
} 

El segundo enfoque, de nido de abeja a IceCreamSandwich:

public class MyNotificationBuilderHoneyCombToIceCreamSandwich { 
Notification.Builder mb = null; 

MyNotificationBuilderHoneyCombToIceCreamSandwich(Context myContext, int icon, String ticker, String title, String info, Long timeStamp, PendingIntent pendingIntent, boolean onGoing) { 
    mb = new Notification.Builder(myContext); 
    mb.setSmallIcon(icon); 
    mb.setContentIntent(pendingIntent); 
    mb.setContentTitle(title); 
    mb.setContentText(info); 
    mb.setWhen(timeStamp); 
    if (ticker != null) mb.setTicker(ticker);  
    mb.setOngoing(onGoing); 
} 

Notification get() { 
    return mb.getNotification(); 
} 
} 

La segunda generación, con el cambio de nombre, Jellybean (en adelante, hasta ahora ...):

public class MyNotificationBuilderJellyBean { 

Notification.Builder mb = null; 

MyNotificationBuilderJellyBean(Context myContext, int icon, String ticker, String title, String info, Long timeStamp, PendingIntent pendingIntent, boolean onGoing) { 
    mb = new Notification.Builder(myContext); 
    mb.setSmallIcon(icon); 
    mb.setContentIntent(pendingIntent); 
    mb.setContentTitle(title); 
    mb.setContentText(info); 
    mb.setWhen(timeStamp); 
    if (ticker != null) mb.setTicker(ticker);  
    mb.setOngoing(onGoing); 
} 

Notification get() { 
    return mb.build(); 
} 
} 

A continuación, sólo tiene que elegir qué clase instanciar sobre la marcha:

// System information 
private final int sdkVersion = Build.VERSION.SDK_INT; 
// If you want to go really old: 
    // (actually, there is a question about how this issue should be handled 
    // systematically. Suggestions welcome.) 
// final int sdkVersion = Integer.parseInt(Build.VERSION.SDK); 

    // This is for a permanent notification. Change the final argument (flags or boolean) if it isn't meant ot be 
    // For meaning of other variable, see notification documentation on the android website. 
    if (sdkVersion < Build.VERSION_CODES.HONEYCOMB) { 
     MyNotificationBuilderToGingerBread mnb = new MyNotificationBuilderToGingerBread(myContext, R.drawable.notification_icon, ticketText, title, infoText, timeStampMillis, pendingIntentForTapOnFullNotitifcation, Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR); 
     notification = mnb.get(); 
    } 
    else if (sdkVersion < Build.VERSION_CODES.JELLY_BEAN) { 
     MyNotificationBuilderHoneyCombToIceCreamSandwich mnb = new MyNotificationBuilderHoneyCombToIceCreamSandwich(myContext, R.drawable.notification_icon, ticketText, title, infoText, timeStampMillis, pendingIntentForTapOnFullNotitifcation, true); 
     notification = mnb.get(); 
    } 
    else { 
     MyNotificationBuilderJellyBean mnb = new MyNotificationBuilderJellyBean(myContext, R.drawable.notification_icon, ticketText, title, infoText, timeStampMillis, pendingIntentForTapOnFullNotitifcation, true); 
     notification = mnb.get(); 
    } 

    // Send the notification. 
    notificationManager.notify(idForNotificationManager, notification); 

Espero que esto ayude!

+0

Excelente respuesta. Muchas gracias – anon

Cuestiones relacionadas