Java-язык с поддержкой Android

Просто интересно, попробовал ли кто-нибудь использовать новые функции языка Java 7 с Android? Я знаю, что Android читает байт-код, который Java выплевывает и превращает его в dex. Поэтому, я думаю, мой вопрос в том, может ли он понять байт-код Java 7?

Ответ 1

Если вы используете Android Studio, язык Java 7 должен быть включен автоматически без каких-либо патчей. Для Try-with-resource требуется API-уровень 19+, а материал NIO 2.0 отсутствует.

Если вы не можете использовать функции Java 7, см. @Nuno ответ на вопрос о том, как отредактировать build.gradle.

Ниже приводится только исторический интерес.


Небольшая часть Java 7, безусловно, может использоваться с Android (примечание: я тестировал только 4.1).

Прежде всего, вы не можете использовать Eclipse ADT, потому что жестко закодировано, что совместимы только Java-компилятор 1.5 и 1.6. Вы можете перекомпилировать ADT, но я считаю, что нет простого способа сделать это, кроме перекомпиляции всего Android вместе.

Но вам не нужно использовать Eclipse. Например, Android Studio 0.3.2, IntelliJ IDEA CE и другие java-совместимые IDE файлы поддерживают компиляцию на Android и, вы можете установить соответствие даже с Java 8 с помощью

  • Файл → Структура проекта → Модули → (выберите модуль на второй панели) → Уровень языка → (выберите "7.0 - Алмазы, ARM, многопользовательский захват и т.д." )

Enabling Java 7 on IntelliJ

Это позволяет использовать возможности языка Java 7 , и вы вряд ли сможете извлечь выгоду из чего-либо, так как половина из них также поступает из библиотеки. Вы можете использовать те, которые не зависят от библиотеки:

  • Алмазный оператор (<>)
  • Строковый переключатель
  • Несколько ловушек (catch (Exc1 | Exc2 e))
  • Подчеркивание в числовых литералах (1_234_567)
  • Бинарные литералы (0b1110111)

И эти функции еще не могут быть использованы:

  • Оператор try -with-resources - потому что для него требуется несуществующий интерфейс "java.lang.AutoCloseable" (это можно использовать публично в 4.4 +)
  • Аннотации @SafeVarargs - потому что "java.lang.SafeVarargs" не существует

... "все же":) Оказывается, хотя Android-библиотека ориентирована на 1,6, источник Android содержит интерфейсы, такие как AutoCloseable и традиционные интерфейсы, такие как Closeable наследуют от AutoCloseable (SafeVarargs действительно отсутствует, хотя). Мы могли бы подтвердить его существование через отражение. Они скрыты просто потому, что Javadoc имеет тег @hide, из-за которого "android.jar" не включал их.

Уже существует существующий вопрос Как мне создать Android SDK со скрытыми и внутренними API-интерфейсами? о том, как получить эти методы назад. Вам просто нужно заменить существующую ссылку "android.jar" текущей платформы на нашу индивидуальную, тогда многие из API Java 7 станут доступны (процедура аналогична процедуре в Eclipse. Проверьте структуру проекта → SDK.)

В дополнение к AutoCloseable (только) доступны также следующие функции библиотеки Java 7 :

  • Конструкторы цепочки исключений в ConcurrentModificationException, LinkageError и AssertionError
  • Статические методы .compare() для примитивов: Boolean.compare(), Byte.compare(), Short.compare(), Character.compare(), Integer.compare(), Long.compare().
  • Currency:.getAvailableCurrencies(),.getDisplayName() (но без .getNumericCode())
  • BitSet:.previousSetBit(),.previousClearBit(),.valueOf(),.toLongArray(),.toByteArray( )
  • Collections:.emptyEnumeration(),.emptyIterator(),.emptyListIterator()
  • AutoCloseable
  • Throwable:.addSuppressed(),.getSuppressed() и конструктор с 4 аргументами
  • Character:.compare(),.isSurrogate(),.getName(),.highSurrogate(),.lowSurrogate(),.isBmpCodePoint() (но без .isAlphabetic() и .isIdeographic())
  • Система:.lineSeparator() (недокументированная?)
  • java.lang.reflect.Modifier:.classModifiers(),.constructorModifiers(),.fieldModifiers(),.interfaceModifiers(),.methodModifiers()
  • NetworkInterface:.getIndex(),.getByIndex()
  • InetSocketAddress:.getHostString()
  • InetAddress:.getLoopbackAddress()
  • Logger:.getGlobal()
  • ConcurrentLinkedDeque
  • AbstractQueuedSynchronizer:.hasQueuedPredecessors()
  • DeflaterOutputStream: 3 конструктора с "syncFlush".
  • Deflater:.NO_FLUSH,.SYNC_FLUSH,.FULL_FLUSH,.deflate() с 4 аргументами

Это в основном все. В частности, NIO 2.0 не существует, а Arrays.asList все еще не @SafeVarargs.

Ответ 2

EDIT: В то время, когда это было написано, последней версией были Android 9 и Eclipse Indigo. С тех пор ситуация изменилась.

  • Практический ответ

Да, я пробовал. Но это не отличный тест, так как совместимость была ограничена уровнем 6 без возможности (по крайней мере, простой способ) использовать java 7:

  • Сначала я установил JDK7 на машине, у которой не было другого JDK, установленного - Eclipse и Android также не установлены:

The 7 is the only installed on this machine

  • Затем я установил совершенно новый Eclipse Indigo и проверил, что на самом деле он использует JDK 7 (ну, так как это единственный, и поскольку это тот, который я выбрал, я был бы удивлен)

The 7 is the only used by this Eclipse

  • Затем я установил последнюю версию Android SDK (EDIT: Honeycomb, API13, на момент написания этой статьи). Он нашел мой JDK 7 и установлен правильно. То же самое для ADT.

  • Но у меня был сюрприз при попытке скомпилировать и запустить приложение Hello Word для Android. Совместимость была установлена ​​на Java 6 без возможности принудительного перехода на Java 7:

Compatibility is limited to Java 6

  • Я пробовал с проектом, отличным от Android, обычным Java, и у меня было объяснение. Уровень совместимости, по-видимому, ограничен Eclipse (см. Сообщение внизу нижеследующего изображения):

Eclipse limits itself to level 6 compatibility

Таким образом, у меня был Hello World, а также другие приложения, более сложные и с использованием SQLite, Listview, Sensor и Camera, но это только доказывает, что обработка совместимости Java 7 выглядит хорошо и работает с Android.

Итак, кто-то пытался с добрым старым Ant, чтобы обойти ограничение Eclipse, увиденное выше?

  • Теоретический ответ

В любом случае, SDK предназначен для использования с Java 5 или 6, как описано здесь.

У нас может быть что-то работающее с Java 7, но оно будет работать "случайно". Здание DEX может работать нормально или нет, и как только DEX будет построен, он может работать или нет. Это связано с тем, что использование неквалифицированного JDK дает непредсказуемые результаты по определению.

Даже если кто-то успешно создал Android-приложение под простой Java 7, это не относится к JDK. Тот же процесс, применяемый к другому приложению, может завершиться неудачей, или в результате приложения могут возникнуть ошибки, связанные с использованием этого JDK. Не рекомендуется.

Для тех, кто участвует в разработке webapps, это точно так же, как развертывание веб-приложения, созданного под Java 5 или 6 под сервером приложений, доступным только для Java 4 (например, Weblogic 8). Это может сработать, но это не то, что можно рекомендовать для других целей, чем пытаться.

Ответ 3

Цитата из dalvikvm.com:

dx, включенный в Android SDK, преобразует файлы классов Java классов Java, скомпилированные обычным компилятором Java в другой формат файла классов (формат .dex)

Это означает, что исходный файл .java не имеет значения, это только байт-код .class.

Насколько я знаю, в JTM-код JVM в Java 7 добавлен только invokedynamic, остальное совместимо с Java 6. Сам язык Java не использует invokedynamic. Другие новые функции, такие как оператор switch с использованием String s или multi- catch, являются просто синтаксическим сахаром и не требуют изменений байтового кода. Например, multi- catch просто копирует catch -block для каждого возможного исключения.

Единственная проблема заключается в том, что новые классы, введенные в Java 7, отсутствуют в Android, например AutoCloseable, поэтому я не уверен, что вы можете использовать try -with-resources (кто-то пробовал?).

Любые комментарии по этому поводу? Я что-то пропустил?

Ответ 4

Начиная с Android SDK v15, наряду с Eclipse 3.7.1, Java 7 поддерживает не для разработки Android. Настройка совместимости источника с 1.7 мандатами, устанавливающая сгенерированную совместимость файла .class с номером 1.7, что приводит к следующей ошибке компилятора Android:

Для Android требуется уровень соответствия компилятора 5.0 или 6.0. Вместо этого найдено "1.7". Используйте Android Tools > Fix Project Properties.

Ответ 5

Чтобы расширить этот ответ от @KennyTM, если вы используете таргетинг 4.0.3 и выше (minSdkVersion = 15), вы можете использовать скрытые API, добавив несколько классов в целевой SDK android.jar.

Как только вы сделаете это, вы можете использовать try-with-resources для любого Closeable, а также реализовать AutoCloseable в своих собственных классах.

Я сделал zip, содержащий источники и двоичные файлы всех классов, которые необходимо было изменить в android.jar, чтобы сделать эти API доступными. Вам просто нужно распаковать его и добавить двоичные файлы в ваш файл android-sdk/platform/android-NN/android.jar

Вы можете скачать его здесь: http://db.tt/kLxAYWbr

Также следует отметить, что за последние пару месяцев Эллиотт Хьюз сделал несколько коммитов для дерева Android: закончил AutoCloseable, добавил SafeVarargs, скрытые различные API, fixed Throwable protected constructor и добавлена ​​поддержка файлов классов версии 51 в dx. Итак, наконец-то начался определенный прогресс.

Изменить (апрель 2014):

С выпуском SDK 19 больше не нужно исправлять файл android.jar с дополнительными API-интерфейсами.

Лучший способ использовать try-in-resources в Android Studio для приложения, которое предназначено для 4.0.3 и выше (minSdkVersion = 15), добавляет следующий compileOptions к вашему build.gradle

android {
    compileSdkVersion 19
    buildToolsVersion '19.0.3'

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 19
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}

Android Studio будет жаловаться, что try-with-resources не могут использоваться с этим уровнем API, но мой опыт в том, что он может. Проект будет строиться и запускаться без проблем на устройствах с 4.0.3 и выше. Я не испытывал никаких проблем с этим приложением, которое было установлено на устройствах 500k +.

Android Studio error

Чтобы игнорировать это предупреждение, добавьте следующее в свой lint.xml:

<issue id="NewApi">
    <ignore regexp="Try-with-resources requires API level 19"/>
</issue>

Ответ 7

Чтобы использовать функции Java 7 в построении кода с помощью системы сборки на основе ant на базе Android, просто добавьте следующее в свой custom_rules.xml в корневой каталог проектов:

custom_rules.xml:

<project name="custom_android_rules">
    <property name="java.target" value="1.7" />
    <property name="java.source" value="1.7" />
</project>

Ответ 8

Некоторые люди могут быть заинтересованы в этом проекте git, который я нашел, что позволяет запускать Java 7 на Android. https://github.com/yareally/Java7-on-Android

Однако слишком большой риск, если я добавлю это в текущий проект, над которым я работаю. Поэтому я подожду, пока Google официально не поддержит Java 7.