java 如何在您的代码中支持多个 android 版本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4552250/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 06:55:22  来源:igfitidea点击:

How to support multiple android version in your code?

javaandroid

提问by dhaval

Take accessing contacts in android android.jar for versions 1.6 has People.CONTENT_URI for invoking contacts related info whereas in later versions we need to have api support for RawContacts.CONTENT_URI.

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

Same thing is true for accessing calendar for instance as its URI is changed in android 2.2.

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

Is there a best practice to manage all different changes without adding additional application or build separately for each version of changes?

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

采纳答案by st0le

Quite Honestly, it's a pain.

老实说,这是一种痛苦。

I usually, just isolate parts of code that are different and access them using abstract classes. So technically creating different version for different OS.

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

But there are other ways. The best one i've seen involves using reflection.

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

回答by Neil Townsend

For my money, a very good answer is at http://android-developers.blogspot.co.uk/2010/07/how-to-have-your-cupcake-and-eat-it-too.html. However, the example there is a little more complicated than need be, so based on that, here is an example of how to cope with it when building notifications. The underlying reason this works is a consequence of how java engines interpret classes: it only looks at them when needed, so if you wrap version specific code up in a class and only create it when you know you are using that version, it all works ...

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

There are, as far as I can tell, two generations of approaches to creating notification, and a naming change along the way in the second. So that gives three ways to do it. For each way, create a class with the notification generation in it:

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

The first approach (used through to Gingerbread):

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

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

The second approach, Honeycomb to IceCreamSandwich:

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

The second generation, with the name change, Jellybean (onwards, so far ...):

第二代,更名后,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();
}   
}

Then, you just need to pick which class to instantiate on the fly:

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

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

Hope this helps!

希望这可以帮助!

回答by omermuhammed

There are many resources for you to utilize to help support multiple versions of android.

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

  1. Read this blog post hereand then read this one here, they will help you address API level version support issues.
  2. Read thisblog post on multiple screen support, especially how the asset hierarchy in parsed in res folder. This will help you understand and design how to do asset folder structure to support different screen size/densities and android versions.
  3. Lastly write your own custom ant build scripts so that you can compile with all versions of android.
  1. 阅读这篇博客文章在这里,然后阅读这一块在这里,他们会帮你的地址API级版本支持问题。
  2. 阅读有关多屏幕支持的这篇博文,尤其是如何在 res 文件夹中解析资产层次结构。这将帮助您理解和设计如何进行资产文件夹结构以支持不同的屏幕尺寸/密度和 android 版本。
  3. 最后编写您自己的自定义 ant 构建脚本,以便您可以使用所有版本的 android 进行编译。

回答by Valentin Rocher

  • If you don't really need the new functionnalities, and really have to support old Android versions, drop it. Build your app for the oldest version, and don't bother with this kind of thing.
  • In the other case, you can detect the version using Build, and use reflection to load the classes you need. An example of that can be found in the source code of the K9Mail app
  • 如果您真的不需要新功能,并且真的必须支持旧的 Android 版本,请放弃它。为最旧的版本构建您的应用程序,不要理会这种事情。
  • 在另一种情况下,您可以使用Build检测版本,并使用反射加载您需要的类。一个例子可以在 K9Mail 应用程序源代码中找到

回答by ubzack

This is a great articlefor when you have to do reflection in Android (to support multiple API levels).

当您必须在 Android 中进行反射(以支持多个 API 级别)时,这是一篇很棒的文章

And when you have to have different resourcesfor different API Levels, this is the reference to use(see the section on "Platform Version (API level)").

并且当您必须为不同的 API 级别拥有不同的资源时这是要使用的参考(请参阅“平台版本(API 级别)”部分)。

回答by Filippo Mazza

If on Eclipse, from ADT version 17 you can specify code to run with some version simply as described in Lint API Check. The code word is @TargetAPI(XX)

如果在 Eclipse 上,从 ADT 版本 17 开始,您可以简单地按照Lint API Check 中的描述指定要在某个版本上运行的代码。码字为@TargetAPI(XX)

Hope it helps

希望能帮助到你

回答by m_vitaly

There's a nice article on android.com about it: http://developer.android.com/resources/articles/backward-compatibility.html

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

Personally I would suggest the wrapper class or wrapper library solution. But in small cases the reflection should be fine (and in case performance is not a problem for you).

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

If you need more info, ask in comments.

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

回答by Barmaley Red Star

Best practice (though not for Android, but for J2ME) to my knowledge is to use preprocessing C/C++ styled statements, like:

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

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

Some IDE's support these kind of preprocessing, e.g. Netbeans. To my knowledge Eclipse has some plugins to enable preprocessing also. I don't really know are they applicable to Android development. Try to google yourself.

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