【问题标题】:How to support multiple android version in your code?如何在您的代码中支持多个 android 版本?
【发布时间】:2010-12-29 07:24:21
【问题描述】:

在 android 中访问联系人 1.6 版的 android.jar 具有 People.CONTENT_URI 用于调用联系人相关信息,而在更高版本中,我们需要对 RawContacts.CONTENT_URI 提供 api 支持。

访问日历也是如此,因为它的 URI 在 android 2.2 中发生了更改。

是否有最佳实践来管理所有不同的更改,而无需为每个更改版本添加额外的应用程序或单独构建?

【问题讨论】:

    标签: java android


    【解决方案1】:

    对于我来说,一个很好的答案是http://android-developers.blogspot.co.uk/2010/07/how-to-have-your-cupcake-and-eat-it-too.html。但是,这里的示例比需要的要复杂一些,因此基于此,这里有一个示例,说明在构建通知时如何应对它。这个工作的根本原因是java引擎如何解释类​​的结果:它只在需要时查看它们,所以如果你将特定于版本的代码包装在一个类中,并且只有在你知道你正在使用该版本时才创建它,这一切都有效...

    据我所知,有两代创建通知的方法,以及第二代的命名更改。所以这提供了三种方法来做到这一点。对于每种方式,创建一个包含通知生成的类:

    第一种方法(用于姜饼):

    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;
    }
    }
    

    第二种方法,Honeycomb to 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();
    }   
    }
    

    第二代,更名,Jellybean(以后,至今...):

    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();
    }   
    }
    

    然后,您只需要即时选择要实例化的类:

    // 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);
    

    希望这会有所帮助!

    【讨论】:

    • 优秀的答案。非常感谢
    【解决方案2】:

    您可以利用许多资源来帮助支持多个版本的 android。

    1. 阅读这篇博文here 和 然后阅读这篇here,他们 将帮助您解决 API 级别 版本支持问题。
    2. 阅读this多个博客文章 屏幕支持,尤其是如何 在 res 中解析的资产层次结构 文件夹。这将帮助你 了解和设计如何做 支持的资产文件夹结构 不同的屏幕尺寸/密度和 安卓版本。
    3. 最后编写您自己的自定义 ant 构建 脚本,以便您可以使用 所有版本的安卓。

    【讨论】:

      【解决方案3】:

      老实说,这很痛苦。

      我通常只隔离不同的代码部分并使用抽象类访问它们。所以在技术上为不同的操作系统创建不同的版本。

      但还有其他方法。我见过的最好的方法是使用反射。

      【讨论】:

      • 是的,这更接近于访问联系人的具体问题。也许需要为额外的数据构建类似的代码,这些数据会在日历等版本上保持 uri 的变化
      【解决方案4】:
      • 如果您真的不需要新功能,并且确实必须支持旧的 Android 版本,请放弃它。为最旧的版本构建您的应用,不要为这种事情烦恼。
      • 另外一种情况,你可以使用Build检测版本,并​​使用反射来加载你需要的类。可以在source code of the K9Mail app 中找到一个示例

      【讨论】:

        【解决方案5】:

        在 android.com 上有一篇关于它的好文章: http://developer.android.com/resources/articles/backward-compatibility.html

        我个人建议使用包装类或包装类库解决方案。但在小情况下,反射应该没问题(如果性能对您来说不是问题)。

        如果您需要更多信息,请在 cmets 中询问。

        【讨论】:

        【解决方案6】:

        This is a great article 用于您必须在 Android 中进行反射(以支持多个 API 级别)时。

        当您必须为不同的 API 级别提供不同的资源时,this is the reference to use(请参阅“平台版本(API 级别)”部分)。

        【讨论】:

        • 很好的答案。这正是我想要的。
        【解决方案7】:

        如果在 Eclipse 上,从 ADT 版本 17 开始,您可以指定代码以使用某些版本运行,就像 Lint API Check 中所述。 代码字是@TargetAPI(XX)

        希望对你有帮助

        【讨论】:

          【解决方案8】:

          据我所知,最佳实践(虽然不是针对 Android,而是针对 J2ME)是使用预处理 C/C++ 样式的语句,例如:

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

          一些 IDE 支持这种预处理,例如网豆。据我所知,Eclipse 也有一些插件可以启用预处理。我真的不知道它们是否适用于 Android 开发。尝试自己用谷歌搜索。

          【讨论】:

          • Netbeans 支持根据配置键包含多个 jar - 实际上用作预处理器#define。坏消息:Netbeans 不支持 Android :) 另一方面,Netbeans 有一个名为 nbandroid 的 Android 插件 - 它处于深度测试阶段(1/2 年前 - 可能已经改变了)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多