Как получить номер версии манифеста из XML-переменных приложения (макета)?

184

Я хотел бы иметь возможность ссылаться на номер версии манифеста проекта в основной части кода. До этого момента я связывал номер версии в XML-файле String с манифестом (@ string / Version). Я хотел бы сделать это наоборот, связать строковую переменную XML с версией в манифесте. Причина? Я хотел бы только изменить номер версии в одном месте, файл манифеста. Есть какой-либо способ сделать это? Спасибо!

PearsonArtPhoto
источник
17
Это не дубликат. Вопрос в том, как сделать то же самое в CODE, который я задаю в XML. Две совершенно разные конструкции в программировании на Android ...
PearsonArtPhoto

Ответы:

367

Я считаю, что здесь уже был дан ответ .

String versionName = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;

ИЛИ

int versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
Константин Буров
источник
8
Почти, но не совсем ... Я хотел бы сослаться на XML-код, но, похоже, это невозможно, поэтому ...
PearsonArtPhoto
Огромное спасибо!!! Я искал повсюду это:String versionName = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
Аарон Клап
1
@ Шуб, я так не думаю.
Константин Буров
3
Добавьте BuildConfig.VERSION_NAME к своему ответу для фальшивых подписей.
Jobbert
102

Нет прямого способа получить версию, но есть два обходных пути, которые можно сделать.

  1. Версия может быть сохранена в строке ресурса и помещена в манифест с помощью:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.somepackage"
         android:versionName="@string/version" android:versionCode="20">
    
  2. Можно создать собственное представление и поместить его в XML. Представление будет использовать это, чтобы назначить имя:

    context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;

Любое из этих решений позволит разместить название версии в XML. К сожалению, не существует хорошего простого решения, вроде того android.R.string.versionили чего-то в этом роде.

PearsonArtPhoto
источник
14
небольшое примечание к 1 .: это работает, но я думаю, что это обескураживает, так как я получаю предупреждение, говорящее мнеThe android:versionName cannot be a resource url, it must be a literal string
Griddo
1
Что я сделал, так это оставил имя версии манифеста нетронутым (но обновлял его при каждом новом выпуске) и использовал string.xml для хранения значения, которое я буду использовать в приложении.
numediaweb
1
Ибо AndroidStudioманифест versionNameпереопределяется одним набором в build.gradleфайле
Adrian C.
67

Вы можете использовать versionNameресурсы XML, такие как макеты действий. Сначала создайте строковый ресурс в app/build.gradleфайле со следующим фрагментом в androidузле:

applicationVariants.all { variant ->
    variant.resValue "string", "versionName", variant.versionName
}

Таким образом, все build.gradleсодержимое файла может выглядеть так:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion '24.0.0 rc3'
    defaultConfig {
        applicationId 'com.example.myapplication'
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 17
        versionName '0.2.3'
        jackOptions {
            enabled true
        }
    }
    applicationVariants.all { variant ->
        variant.resValue "string", "versionName", variant.versionName
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
} 

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.android.support:design:23.3.0'
    compile 'com.android.support:support-v4:23.3.0'
}

Тогда вы можете использовать @string/versionNameв XML. Android Studio помечает его красным, но приложение будет компилироваться без проблем. Например, это можно использовать так app/src/main/res/xml/preferences.xml:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory
        android:title="About"
        android:key="pref_key_about">

        <Preference
            android:key="pref_about_build"
            android:title="Build version"
            android:summary="@string/versionName" />

    </PreferenceCategory>


</PreferenceScreen>
Арун Шанкар
источник
3
@DenisGL michiganlabs.com/…
Арун Шанкар
3
Это лучше, чем программный стиль.
Нейротрансмиттер
2
Прекрасное решение. Благодаря тонну.
Самик Bandyopadhyay
2
Я использую последние и до сих пор работает для меня. Я использую эту и несколько других переменных, как это. @ k2col какую ошибку ты получаешь при компиляции? Просьба опубликовать ваш код gradle
Арун Шанкар
3
Это следует считать лучшим ответом.
ЭЧАЯ
15

Я решил эту проблему, расширив класс Preference.

package com.example.android;

import android.content.Context;
import android.preference.Preference;
import android.util.AttributeSet;

public class VersionPreference extends Preference {
    public VersionPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        String versionName;
        final PackageManager packageManager = context.getPackageManager();
        if (packageManager != null) {
            try {
                PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
                versionName = packageInfo.versionName;
            } catch (PackageManager.NameNotFoundException e) {
                versionName = null;
            }
            setSummary(versionName);
        }
    }
}

Тогда в моих настройках XML:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <com.example.android.VersionPreference android:title="Version" />
</PreferenceScreen>
seastland
источник
К сожалению. Должно быть, я думал о предпочтениях XML на основе другого комментария.
Seastland
Тем не менее, я все равно просто скопирую и вставлю его ответ.
Mathijs Segers
13

Я использую BuildConfig.VERSION_NAME.toString();. Какая разница между этим и получением его из packageManager?

Извините, у меня нет решений на основе XML.

Mullazman
источник
7
BuildConfig.VERSION_NAME уже является строкой, нет необходимости вызывать toString () для нее.
Макотосан
Привычка. Достаточно справедливо
Mullazman
Есть случаи, когда вызов этого в вашем проекте может получить результат, отличный от ожидаемого. Например, если вы используете подмодуль Android в своем проекте и вызываете его из кода подмодуля, он будет ссылаться на конфигурацию сборки подмодуля, которая может иметь другую версию. Или, если вы вызываете его из кода вашего проекта, вы можете по ошибке сослаться на конфигурацию вашего подмодуля и получить тот же результат. Просто будьте осторожны и дважды проверьте, что вы ссылаетесь на соответствующий пакет конфигурации сборки.
MikeL
Попробуйте использовать это руководство: medium.com/@manas/…
CrandellWS
Разница в том, что BuilConfig предоставляется Gradle, тогда как получение его во время выполнения осуществляется PackageManager (OS)
Ишаан Кумар
12

Если вы используете Gradle, вы можете использовать файл build.gradle, чтобы программно добавить значение к ресурсам xml во время компиляции.

Пример кода, извлеченный из: https://medium.com/@manas/manage-your-android-app-s-versioncode-versionname-with-gradle-7f9c5dcf09bf

buildTypes {
    debug {
        versionNameSuffix ".debug"
        resValue "string", "app_version", "${defaultConfig.versionName}${versionNameSuffix}"
    }
    release {
        resValue "string", "app_version", "${defaultConfig.versionName}"
    }
}

теперь используйте по @string/app_versionмере необходимости в XML

Это добавит .debugк названию версии, как описано в связанной статье, в режиме отладки.

CrandellWS
источник
1
лучший ответ когда-либо !!
Рахил Хасан
2

Вы не можете использовать его из XML.

Вам нужно расширить виджет, который вы используете в XML, и добавить логику для задания текста, используя то, что упомянуто в ответе Константина Бурова.

Macarse
источник
Я боялся этого ... Спасибо за помощь!
PearsonArtPhoto
2
мы можем использовать это. пожалуйста, проверьте мой ответ. Я использую его в своем приложении
Арун Шанкар
1

Самым простым решением является использование BuildConfig.

Я использую BuildConfig.VERSION_NAMEв своем приложении.

Вы также можете использовать, BuildConfig.VERSION_CODEчтобы получить код версии.

CHAUHAN
источник
-3

Поздно к игре, но вы можете сделать это без @string/xyzиспользования?android:attr

    <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="?android:attr/versionName"
     />
    <!-- or -->
    <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="?android:attr/versionCode"
     />
ddrscott
источник
11
Я использую как это:, <Preference android:title="Version" android:summary="?android:attr/versionName" ></Preference>но показать как. ?16843292Что не так?
Suge
Я не уверен, но думаю, что это для более поздних API?
Mafro34
@PearsonArtPhoto на самом деле, где это говорит?
Mafro34
не работает; смешной номер вывел следующую который @Suge указано выше
ЭЧАЯ
вообще не работает и возвращает случайное значение, как было ранее опубликовано
A_rmas