如何确定我的应用程序正在运行在安卓系统上

28

我有一个运行在多个移动设备上的应用程序,这些设备运行着Fedora或Android操作系统。为了合并我的代码库和发布版本,我想要确定当前设备的操作系统。我尝试过使用System.getProperty("os.name"),但它只返回“Linux”。在System属性中,是否有一些特定于Android的属性可以用来区分操作系统?


4
可能是如何在Java中编程确定操作系统?的重复问题。 - jww
@jww,“os.name”属性在Android上为null,这是大多数答案依赖的。那些不依赖于Apache Commons的答案没有检查Android。 - TheWanderer
5个回答

32

你可以检查几个属性。候选属性包括:

  • java.vendor.url --> http://www.android.com
  • java.vm.name --> Dalvik(我不知道 Fedora 使用哪一个...)
  • java.vm.vendor --> The Android Project
  • java.vendor --> The Android Project

也许你想自己检查一下?

Properties p = System.getProperties();
Enumeration keys = p.keys();
while(keys.hasMoreElements()) {
   String key = (String) keys.nextElement();
   String value = (String) p.get(key);
   System.out.println(key + " >>>> " + value);
}

3
谢谢,我选择了“java.runtime.name” =“android runtime”。 - Tim OMalley
2
你好,这确实非常有帮助。安卓开发人员方面是否有任何官方声明,说明其中哪些将保持不变?谢谢。 - Animesh
4
简短版:System.getProperties().list(System.out);翻译:打印系统属性到控制台。 - Julian Fondren
@user552447 应该是“Android运行时”。 - Ahmet Noyan Kızıltan
5
从Android 5开始,java.runtime.name 返回null。因此,它不是可靠的。 - Ahmet Noyan Kızıltan

7

我不了解安卓系统,但如果你找不到某些独特的系统属性,有时可以通过检测是否存在某些特定的类来确定该系统。因此,您可以执行以下操作:

boolean isAndroid() {
    try {
        Class.forName("the class name");
        return true;
    } catch(ClassNotFoundException e) {
        return false;
    }
}

1
+1 你可以在Android包中寻找一个类,例如Activity。 - Vincent Mimoun-Prat
1
这也是一个不错的想法,但源代码可能有也可能没有android.jar。 - Tim OMalley
当使用像Robolectrics这样的测试工具时,这种方法将无法正常工作。 - Rafael Winterhalter
1
我正在使用 android.os.Build 类来实现这个方法 - 这是Android应用程序预期检查不同Android平台配置的类,请参见https://developer.android.com/reference/android/os/Build。因此,如果您的应用程序想要了解的不仅是它是否为Android,而且还想知道正在运行的Android类型,则实际上需要获取到 Build 的类引用。 - Guss
另外,您可以寻找 Android 平台没有提供的类,比如 java.lang.instrument.ClassFileTransformer(自 Java 5 起)。 - neuralmer

3

以下是我根据此页面的信息编写的一些代码,以防您想要复制粘贴:

private static YLogger ylogger;
public static YLogger getLogger() {
    if (ylogger == null){
        // need to find a new logger. Let's check if we have Android running
        if (System.getProperty("java.vm.name").equalsIgnoreCase("Dalvik")){
            ylogger = new AndroidLogger();
            ylogger.d("YLoggerFactory", "Instantiating Android-based logger");
        } else {
            // fallback option, system logger.
            ylogger = new SystemLogger();   
            ylogger.d("YLoggerFactory", "Instantiating System-based logger");
        }
    }
    return ylogger;
}

2
这可能会在ART上出现问题。 - Christian Brüggemann
有点hack,但这可能有所帮助。boolean isAndroid; try { Class.forName("android.app.Activity"); isAndroid = true; } catch (ClassNotFoundException e) { isAndroid = false; } - jasxir
你如何在后端编译它(不带Android库)?由于缺少AndroidLogger类,它将会失败。 - Luka Bradeško

2

这似乎是最稳定、相当清晰和冗长的解决方案。在一个正常的/Java.Oracle JVM上,这个属性返回“Oracle Corporation”。 - hoijui
Java在Java 6成为最新版本时被Oracle从SUN接管,因此至少在Java 5之前,这将是一个不同的值。 - hoijui

0

我在我的处理程序草图中使用这个来确定我正在运行的模式,即我在哪里运行它。

enum Mode {
  java, android
}

Mode getMode() {
  return System.getProperty("java.runtime.name").equals("Android Runtime") ? Mode.android : Mode.java;
}

if (getMode() == Mode.java){
  // do something
  // eg: do something that android can't handle
} else {
  // do android stuff 
  // eg: scale the sketch by 2 to improve visibility
}

你需要使用equals()而不是"=="来比较字符串。 - Peter Quiring
@PeterQuiring 这是最佳实践吗?对我来说,“==”是有效的。 - Phani Rithvij
通常情况下,这在Java中不应该起作用。==仅比较对象是否完全相同。equals()将对char数组进行深度比较。 - Peter Quiring
如果编译器正在去重字符串,那么它可能会偶然起作用,因为两个对象将是相同的。 - Peter Quiring
@PeterQuiring 我修改了它。感谢你纠正我的错误。 - Phani Rithvij

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接