5

我在 Android Market 中注意到,许多流行的应用程序都向后兼容更早版本的 Android。例如

Evernote - 1.6
Faceobook Messenger - 2.2

这些应用程序看起来和工作都很棒,但它们如何做到这一点并支持更旧的 API 级别?他们是否仅使用存在于支持的最低操作系统版本中的 API 功能,几乎没有?我假设他们必须使用更高 API 级别的某些功能来提供出色的 UI 和功能列表。

我可以看到两种可能的解决方案:

Use Min/Target API levels in build. Then through code you check the OS version and implement the features using a supported method and degrade gracefully. This seems like a lot of work.

Have multiple app versions targeting various OS versions. E.g. A release for 2.2 and another for 4.0. Is this possible?

问的原因是我正在计划一个应该支持 2.2 的新应用程序,但我担心我可能需要仅在以后版本中可用的 API 功能?我应该只针对 2.2 吗?

编辑:另外,兼容性库扮演什么角色?这是关键吗?

谢谢。

4

3 回答 3

15

我们(Evernote)做了额外的工作来支持 1.6 并尽可能多地使用新的 API。支持 1.6 的主要问题是 Dalvik 对您的类进行了贪婪搜索。这使得无法使用类似的代码

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
    prefEditor.apply();
} else {
    prefEditor.commit();
}

因为它会抛出一个类验证错误。这是当 dalvik 看到您的方法并尝试在运行时访问它时引起的。

相反,您需要使用帮助类来为 SDK 实例化适当的类。是的,这是更多的工作

public abstract class SharedPreferenceEditor {

  private static SharedPreferenceEditor sInstance;

  public static SharedPreferenceEditor getInstance() {
    if (sInstance == null) {

      /*
      * Check the version of the SDK we are running on. Choose an
      * implementation class designed for that version of the SDK.
      */
      @SuppressWarnings("deprecation")
      int sdkVersion = Build.VERSION.SDK_INT;
      if(Evernote.DEBUG)Log.d("SharedPreferenceEditor", "sdkVersion=" + sdkVersion);
      if (sdkVersion < Build.VERSION_CODES.GINGERBREAD) {
        sInstance = new CommitSharedPreferenceEditor();
      } else  {
        sInstance = new ApplySharedPreferenceEditor();
      }
    }
    return sInstance;
  }

  public abstract void save(SharedPreferences.Editor editor);
}

然后你有一个姜饼+ api级别

public class ApplySharedPreferenceEditor extends SharedPreferenceEditor {
  public void save(SharedPreferences.Editor editor) {
    editor.apply();
  }
}

一个用于<姜饼级别

public class CommitSharedPreferenceEditor extends SharedPreferenceEditor{
  public void save(SharedPreferences.Editor editor) {
    editor.commit();
  }
}

我建议支持 2.1 及更高版本,这样您就可以利用对 Dalvik 的改进并使用我列出的第一个示例。

于 2012-09-05T23:05:13.940 回答
6

有几种不同的策略可以将向后支持与最新功能混合。Android 文档中有很多参考资料,但可能从这里开始: Android 应用程序的向后兼容性

但总的来说,我强烈建议您尽可能避免发布多个版本。使用您应用的清单来定位适当范围的操作系统版本和相应的代码。

是的,还有标准的Android Support (Compatibility) Library。通常,兼容库的目的是允许您的应用程序使用一些最新的操作系统功能,同时为旧平台提供一些类似的实现。你绝对应该调查一下。

还有一些很棒的 3rd 方兼容性库。以下是我在项目中使用过的一些,绝对推荐:

请注意,NineOldAndroids 实际上包含在 ActionBarSherlock 中。

于 2012-09-04T22:59:09.300 回答
1

您可以做一些事情来支持旧版本的 Android 平台,同时仍然利用新版本中的功能。支持不同平台版本的 Android 培训指南概述了一些,并有示例代码向您展示如何实现它们。

没有特别的顺序:

  • 您可以设置单独的“minSdkVersion”和“targetSdkVersion”。minSdkVersion 是您想要支持的最早的 Android 版本。targetSdkVersion 是您测试过的最新版本,也是您打算在应用程序中包含的最新功能/行为集。

  • 您可以在运行时检查系统版本,并且仅当设备上运行所需的 Android 平台版本时才实施功能。这看起来像:

    private void setUpActionBar() {
        // Make sure we're running on Honeycomb or higher to use ActionBar APIs
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
          ActionBar actionBar = getActionBar();
          actionBar.setDisplayHomeAsUpEnabled(true);
        }
    }
    
  • 支持库(通常也称为兼容性库)包含来自新版本 Android 的功能,以这样一种方式编写,您可以将它们包含在您的应用程序中,并且它们甚至可以在版本的 Android 上工作。例如,在 Honeycomb (Api 11) 中引入了 Fragments。但是您可以在回到 Donut (Api 4) 的设备上使用支持库中包含的 Fragments 版本!

于 2012-09-05T00:25:52.700 回答