如何获取Android应用程序的构建版本号?

Fah*_*ikh 1198 android android-manifest android-emulator

我需要弄清楚如何为我的Android应用程序获取或制作内部版本号.我需要在UI中显示内部版本号.

我必须做点什么AndroidManifest.xml吗?

plu*_*us- 1975

使用:

try {
    PackageInfo pInfo = context.getPackageManager().getPackageInfo(getPackageName(), 0);
    String version = pInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

您可以使用此方法获取版本代码

int verCode = pInfo.versionCode;
Run Code Online (Sandbox Code Playgroud)

  • @Felix你不能叫getPackageManager()上下文之外,所以getApplicationContext()(或传递的上下文中)可能需要. (50认同)
  • 当`getPackageInfo()`时,不要忘记`try ... catch..` (35认同)
  • 如果你只想获得应用程序的版本,这是两个复杂的.你应该按照[here](http://stackoverflow.com/a/21119027/5389530)的建议使用`BuildConfig.VERSION _**`. (23认同)
  • @Gubatron我在下面的回答允许静态检索这些值. (4认同)
  • 如果您在某些静态方法中需要此数字而无法传递上下文,该怎么办?我的设计不好? (2认同)
  • @AndroidGuy 我们真的需要那个吗?如果 **running** 应用程序无法获取自己的包信息,我会说崩溃是非常合适的。 (2认同)

Sam*_*zor 1790

如果您使用的是Gradle插件/ Android Studio,则从版本0.7.0开始,版本代码和版本名称可以静态使用BuildConfig.确保导入应用程序的包,而不是另一个BuildConfig:

import com.yourpackage.BuildConfig;
...
int versionCode = BuildConfig.VERSION_CODE;
String versionName = BuildConfig.VERSION_NAME;
Run Code Online (Sandbox Code Playgroud)

不需要Context对象!

另外,请确保在build.gradle文件中指定它们而不是AndroidManifest.xml.

defaultConfig {
    versionCode 1
    versionName "1.0"
}
Run Code Online (Sandbox Code Playgroud)

  • 这实际上比所有上下文和包管理器好很多,谢谢. (166认同)
  • 您需要导入正确的包才能使用:`import com.yourapppackage.android.BuildConfig` (38认同)
  • @BinoyBabu如果你在`build.gradle`文件中为你的应用指定了`versionName`,它永远不会显示为空字符串. (16认同)
  • 实际上这是Android Studio推出后的最佳解决方案!+1来自我的身边 (15认同)
  • 它不太可靠.版本名称大多数时间显示为空字符串. (14认同)
  • @JoshPinter这正是我在评论中说的几行:) (6认同)
  • 请注意,对于多模块项目,在特定模块中查询时可能会出现意外结果.可能最好将它绑定在主Application/Activity类的某个全局名称空间中. (4认同)
  • 如果要在库模块中使用它来获取有关应用程序的信息,则此方法无效.库模块中没有BuildConfig文件 (4认同)
  • @dumazy.可以有一个用于库模块的BuildConfig,但是您不会获得应用程序的构建信息.您将获得图书馆的信息. (4认同)
  • 这不适用于“com.android.tools.build:gradle:1.3.0” (3认同)

sco*_*yab 425

如果您只想要版本名称,则稍微缩短版本.

String versionName = context.getPackageManager()
    .getPackageInfo(context.getPackageName(), 0).versionName;
Run Code Online (Sandbox Code Playgroud)

  • 优秀.这应该包含在NameNotFoundException的try/catch中. (79认同)
  • +1我已经实施了你的解决方案,效果很好!但是,这个解决方案应该被try和catch包围,就像Igor所说的那样,将每个方法调用放在一个单独的行而不是调用context.methodName().subMethod().anotherSubMethod()等是很好的做法(例如用于调试).在一条线上.因此,我提供了一个更清洁的解决方案[下](http://stackoverflow.com/a/18352981/1694500) (6认同)
  • 对于使用Gradle的用户-有一个更简单的解决方案。请参阅下面的答案。 (2认同)
  • @IgorGanapolsky:确实如此,但是如果程序员不理解怎么办?我认为应用程序的用户不会欣赏任何类型的异常。对于各种 Android 风格,都会发生一些意想不到的事情发生的变化,当像这样简单的事情关闭你的应用程序时,这将是愚蠢的。如果发生这种情况,您可以假设程序员不理解用户想要什么,因为很容易避免这种情况。此外,如果你想知道出了什么问题,你可以记录异常,有一个描述。无论哪种异常,未经处理的异常都是错误的。 (2认同)

Mer*_*mis 164

你需要两个部分:android:versionCode android:versionName

versionCode是一个数字,您提交给市场的应用程序的每个版本都需要比最后一个更高的数字.

VersionName是一个字符串,可以是您想要的任何字符串.您可以在此处将应用定义为"1.0"或"2.5"或"2 Alpha EXTREME!" 管他呢.

例:

科特林:

val manager = this.packageManager
val info = manager.getPackageInfo(this.packageName, PackageManager.GET_ACTIVITIES)
toast("PackageName = " + info.packageName + "\nVersionCode = "
            + info.versionCode + "\nVersionName = "
            + info.versionName + "\nPermissions = " + info.permissions)
Run Code Online (Sandbox Code Playgroud)

Java的:

PackageManager manager = this.getPackageManager();
PackageInfo info = manager.getPackageInfo(this.getPackageName(), PackageManager.GET_ACTIVITIES);
Toast.makeText(this,
     "PackageName = " + info.packageName + "\nVersionCode = "
       + info.versionCode + "\nVersionName = "
       + info.versionName + "\nPermissions = " + info.permissions, Toast.LENGTH_SHORT).show();
Run Code Online (Sandbox Code Playgroud)

  • Android的官方描述`android:versionCode`和`android:versionName`可以在这里找到:http://developer.android.com/tools/publishing/versioning.html#appversioning (5认同)
  • **这个**在这种情况下是Context .ie Activity,Service .etc (2认同)
  • 当你粘贴一些示例代码是有用的来解释参数的含义....虽然每个人都可以理解`this.getPackageName()`代表`0`你只是吐了没有关于意义的线索 (2认同)

Jos*_*ter 142

使用Gradle和BuildConfig

从BuildConfig获取VERSION_NAME

BuildConfig.VERSION_NAME
Run Code Online (Sandbox Code Playgroud)

是的,现在就这么简单.

它是否为VERSION_NAME返回空字符串?

如果你得到一个空字符串,BuildConfig.VERSION_NAME那么请继续阅读.

我一直得到一个空字符串,BuildConfig.VERSION_NAME因为我没有设置versionName我的成绩构建文件(我从ANT迁移到Gradle).因此,以下是确保您设置VERSION_NAMEvia Gradle的说明.

的build.gradle

def versionMajor = 3
def versionMinor = 0
def versionPatch = 0
def versionBuild = 0 // bump for dogfood builds, public betas, etc.

android {

  defaultConfig {
    versionCode versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild

    versionName "${versionMajor}.${versionMinor}.${versionPatch}"
  }

}
Run Code Online (Sandbox Code Playgroud)

注意:这是来自杰出的杰克沃顿.

删除versionNameversionCodeAndroidManifest.xml

既然你已经设置的versionName,并versionCode在在build.gradle现在的文件,你也可以从你删除这些AndroidManifest.xml文件,如果它们的存在.

  • 只要您从应用程序项目访问BuildConfig,而不是应用程序项目中使用的库,这就很有效.否则,您将获得库项目的BuildConfig,而不是应用程序. (4认同)
  • @JohnCummings 如果您 `import com.package.name.BuildConfig;` 或直接在代码中引用它,即使在项目库中,它也可以工作;) (2认同)

Mic*_*ael 54

这是一个基于scottyab解决方案的清洁解决方案(由Xavi编辑).它显示了如何首先获取上下文,如果它不是由您的方法提供的.此外,它使用多行而不是每行调用多个方法.这使您在调试应用程序时更容易.

Context context = getApplicationContext(); // or activity.getApplicationContext()
PackageManager packageManager = context.getPackageManager();
String packageName = context.getPackageName();

String myVersionName = "not available"; // initialize String

try {
    myVersionName = packageManager.getPackageInfo(packageName, 0).versionName;
} catch (PackageManager.NameNotFoundException e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

现在您已在String中收到版本名称myVersionName,您可以将其设置为TextView或您喜欢的任何内容.

// set version name to a TextView
TextView tvVersionName = (TextView) findViewById(R.id.tv_versionName);
tvVersionName.setText(myVersionName);
Run Code Online (Sandbox Code Playgroud)

  • 你觉得NNFE真的可以扔吗?在包管理器中找不到正在运行的应用程序会很奇怪:) (3认同)

Vel*_*m M 30

使用BuildConfig类

String versionName = BuildConfig.VERSION_NAME;
int versionCode = BuildConfig.VERSION_CODE;
Run Code Online (Sandbox Code Playgroud)

的build.gradle(APP)

 defaultConfig {
    applicationId "com.myapp"
    minSdkVersion 19
    targetSdkVersion 27
    versionCode 17
    versionName "1.0"
   }
Run Code Online (Sandbox Code Playgroud)


Gas*_*lén 25

Kotlin 单线

val versionCode = BuildConfig.VERSION_CODE
val versionName = BuildConfig.VERSION_NAME
Run Code Online (Sandbox Code Playgroud)

确保导入BuildConfig到您的类中。

Java 单线

String versionCode = String.valueOf(BuildConfig.VERSION_CODE);
String versionName = String.valueOf(BuildConfig.VERSION_NAME);
Run Code Online (Sandbox Code Playgroud)

  • 这种方法的缺点是,如果您在库模块中包含此代码,它将向您显示库的版本,而不是应用程序本身。 (2认同)

Sea*_*all 23

如果您正在使用PhoneGap,请创建自定义PhoneGap插件:

在应用包中创建一个新类:

package com.Demo; //replace with your package name

import org.json.JSONArray;

import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;

import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import com.phonegap.api.PluginResult.Status;

public class PackageManagerPlugin extends Plugin {

    public final String ACTION_GET_VERSION_NAME = "GetVersionName";

    @Override
    public PluginResult execute(String action, JSONArray args, String callbackId) {
        PluginResult result = new PluginResult(Status.INVALID_ACTION);
        PackageManager packageManager = this.ctx.getPackageManager();

        if(action.equals(ACTION_GET_VERSION_NAME)) {
            try {
                PackageInfo packageInfo = packageManager.getPackageInfo(
                                              this.ctx.getPackageName(), 0);
                result = new PluginResult(Status.OK, packageInfo.versionName);
            }
            catch (NameNotFoundException nnfe) {
                result = new PluginResult(Status.ERROR, nnfe.getMessage());
            }
        }

        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

在plugins.xml中,添加以下行:

<plugin name="PackageManagerPlugin" value="com.Demo.PackageManagerPlugin" />
Run Code Online (Sandbox Code Playgroud)

在您的deviceready事件中,添加以下代码:

var PackageManagerPlugin = function() {

};
PackageManagerPlugin.prototype.getVersionName = function(successCallback, failureCallback) {
    return PhoneGap.exec(successCallback, failureCallback, 'PackageManagerPlugin', 'GetVersionName', []);
};
PhoneGap.addConstructor(function() {
    PhoneGap.addPlugin('packageManager', new PackageManagerPlugin());
});
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过执行以下操作获取versionName属性:

window.plugins.packageManager.getVersionName(
    function(versionName) {
        //do something with versionName
    },
    function(errorMessage) {
        //do something with errorMessage
    }
);
Run Code Online (Sandbox Code Playgroud)

来自这里这里.

  • 问题不在于PhoneGap.你的回答可能会让人感到困惑. (9认同)
  • @BobbyJ在问题,标题或标签中没有指明问题是关于本机应用程序的.这是谷歌在我寻找答案时提出来的,并且会节省我几个小时. (8认同)

Ric*_*rdo 23

这个问题有两种不同的情况,任何答案都没有正确解决。

场景 1:您没有使用模块

如果您不使用模块,您可以访问您的 BuildConfig 文件并立即获取版本代码:

val versionCode = BuildConfig.VERSION_CODE 
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为这是您的应用程序级别的 BuildConfig 文件,因此它将包含对您的应用程序版本代码的引用

场景 2:您的应用程序有许多模块,并且您假装从模块层次结构中较低的模块访问应用程序版本代码

您拥有许多具有给定层次结构的模块是正常的,例如应用程序 - >数据 - >域 - > ui等。在这种情况下,如果您从“ui”模块访问BuildConfig文件,它不会给您一个引用应用程序版本代码,但引用该模块的版本代码。

为了获取应用程序版本代码,您可以使用以下给定代码:

首先是一个扩展函数来获取PackageInfo

@Suppress("DEPRECATION")
fun Context.getPackageInfo(): PackageInfo {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        packageManager.getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(0))
    } else {
        packageManager.getPackageInfo(packageName, 0)
    }
}
Run Code Online (Sandbox Code Playgroud)

获取版本号的扩展函数

fun Context.getVersionCode(): Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    getPackageInfo().longVersionCode.toInt()
} else {
    getPackageInfo().versionCode
}
Run Code Online (Sandbox Code Playgroud)

版本名称的方法类似:

fun Context.getVersionName(): String = try {
    getPackageInfo().versionName
} catch (e: PackageManager.NameNotFoundException) {
    ""
}
Run Code Online (Sandbox Code Playgroud)

  • 这是截至 2023 年唯一正确的答案。 (2认同)

小智 19

获取应用版本或用于通过其版本代码标识apk的构建代码。版本代码用于在更新,发布等时检测实际的构建配置。

int versionCode = BuildConfig.VERSION_CODE;
Run Code Online (Sandbox Code Playgroud)

版本名称用于显示开发顺序的用户或开发人员。您可以根据需要添加任何版本名称

String versionName = BuildConfig.VERSION_NAME;
Run Code Online (Sandbox Code Playgroud)


May*_*rma 19

与 2020 年一样:从 API 28(Android 9(Pie))开始,不推荐使用“versionCode”,因此我们可以使用“longVersionCode”

Kotlin 中的示例代码

val manager = context?.packageManager
val info = manager?.getPackageInfo(
    context?.packageName, 0
)

val versionName = info?.versionName
val versionNumber = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                        info?.longVersionCode
                    } else {
                        info?.versionCode
                    }
Run Code Online (Sandbox Code Playgroud)


Tus*_*tel 12

对于xamarin用户,请使用此代码获取版本名称和代码

1)版本名称:

public string getVersionName(){
      return Application.Context.ApplicationContext.PackageManager.GetPackageInfo(Application.Context.ApplicationContext.PackageName, 0).VersionName;
}
Run Code Online (Sandbox Code Playgroud)

2)版本代码:

public string getVersionCode(){
      return Application.Context.ApplicationContext.PackageManager.GetPackageInfo(Application.Context.ApplicationContext.PackageName, 0).VersionCode;
}
Run Code Online (Sandbox Code Playgroud)


D.A*_*pun 12

版本名称:BuildConfig.VERSION_NAME 版本代码:BuildConfig.VERSION_CODE


Irf*_*aza 11

如果要在xml上使用它,请在gradle文件中添加以下行:

applicationVariants.all { variant ->
    variant.resValue "string", "versionName", variant.versionName
}
Run Code Online (Sandbox Code Playgroud)

然后在你的xml上使用它,如下所示:

<TextView
        android:gravity="center_horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/versionName" />
Run Code Online (Sandbox Code Playgroud)


Mon*_*man 11

不,您不需要使用AndroidManifest.xml做任何事情

基本上,您的应用的版本名称和版本代码位于应用级别gradle文件中的defaultConfig标签下:

defaultConfig {  
   versionCode 1  
   versionName "1.0"  
}  
Run Code Online (Sandbox Code Playgroud)

注意:当您希望在Play商店中上传应用时,可以使用任何名称作为版本名称,但是如果此应用已在Play商店中,则该版本代码必须与当前版本代码不同。

只需使用以下代码段即可从应用程序中的任何位置获取版本代码版本名称

try {  
    PackageInfo pInfo =   context.getPackageManager().getPackageInfo(context.getPackageName(), 0);  
    String version = pInfo.versionName;  
    int verCode = pInfo.versionCode;  
} catch (PackageManager.NameNotFoundException e) {  
    e.printStackTrace();  
}  
Run Code Online (Sandbox Code Playgroud)

  • versionCode 在 API 28 中已弃用。如文档中所述,请改用 longVersionCode;https://developer.android.com/reference/android/content/pm/PackageInfo.html#versionCode (2认同)

Pra*_*ani 9

总是用try catch块来做:

String versionName = "Version not found";

try {
    versionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
    Log.i(TAG, "Version Name: " + versionName);
} catch (NameNotFoundException e) {
    // TODO Auto-generated catch block
    Log.e(TAG, "Exception Version Name: " + e.getLocalizedMessage());
}
Run Code Online (Sandbox Code Playgroud)


Gev*_*rva 9

以下是获取版本代码的方法:

public String getAppVersion() {
    String versionCode = "1.0";
    try {
        versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
    } catch (PackageManager.NameNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return versionCode;
}
Run Code Online (Sandbox Code Playgroud)

  • 更好的方法 - BuildConfig.VERSION_CODE (3认同)

Ami*_*dat 9

对于Api 28,不推荐使用PackageInfo.versionCode,因此请在下面使用此代码:

    Context context = getApplicationContext();
    PackageManager manager = context.getPackageManager();
    try {
        PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
        myversionName = info.versionName;
        versionCode = (int) PackageInfoCompat.getLongVersionCode(info);
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        myversionName = "Unknown-01";
    }
Run Code Online (Sandbox Code Playgroud)


小智 8

我通过使用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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


moh*_*hax 7

有一些方法可以获得versionCodeversionName编程.

  1. 从中获取版本PackageManager.这是大多数情况下的最佳方式.
try {
    String versionName = packageManager.getPackageInfo(packageName, 0).versionName;
    int versionCode = packageManager.getPackageInfo(packageName, 0).versionCode;
} catch (PackageManager.NameNotFoundException e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
  1. 从生成中获取它BuildConfig.java.但请注意,如果您将在库中访问此值,它将返回使用此库的库版本,而不是应用程序之一.所以只在非库项目中使用!
String versionName = BuildConfig.VERSION_NAME;
int versionCode = BuildConfig.VERSION_CODE;
Run Code Online (Sandbox Code Playgroud)

除了在库项目中使用第二种方式外,还有一些细节.在新的android gradle插件(3.0.0+)中删除了一些功能.所以,就目前而言,即设置不同版本的不同版本不正确.

方式不正确:

applicationVariants.all { variant ->
    println('variantApp: ' + variant.getName())

    def versionCode = {SOME_GENERATED_VALUE_IE_TIMESTAMP}
    def versionName = {SOME_GENERATED_VALUE_IE_TIMESTAMP}

    variant.mergedFlavor.versionCode = versionCode
    variant.mergedFlavor.versionName = versionName
}
Run Code Online (Sandbox Code Playgroud)

上面的代码将正确设置值BuildConfig,但是PackageManager您将收到0,null如果您没有在default配置中设置版本.所以你的应用程序将0在设备上有版本代码.

有一个解决方法 - apk手动设置输出文件的版本:

applicationVariants.all { variant ->
    println('variantApp: ' + variant.getName())

    def versionCode = {SOME_GENERATED_VALUE_IE_TIMESTAMP}
    def versionName = {SOME_GENERATED_VALUE_IE_TIMESTAMP}

    variant.outputs.all { output ->
        output.versionCodeOverride = versionCode
        output.versionNameOverride = versionName
    }
}
Run Code Online (Sandbox Code Playgroud)


Jef*_*f.H 6

上面提到了这段代码,但是这里再次包括在内.你需要一个try/catch块,因为它可能抛出一个"NameNotFoundException".

try {
   String appVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
} catch (PackageManager.NameNotFoundException e) {e.printStackTrace();}
Run Code Online (Sandbox Code Playgroud)

我希望这能为后来的人简化事情.:)


小智 5

但是,不需要应用程序UI的BuildConfig信息的人想要使用这些信息来设置CI作业配置或其他人,比如我.

只要您成功构建项目,就会在项目目录下有一个自动生成的文件BuildConfig.java.

{WORKSPACE} /建立/生成/源极/ buildConfig/{调试|释放}/{PACKAGE} /BuildConfig.java

/**
* Automatically generated file. DO NOT MODIFY
*/
package com.XXX.Project;

public final class BuildConfig {
    public static final boolean DEBUG = Boolean.parseBoolean("true");
    public static final String APPLICATION_ID = "com.XXX.Project";
    public static final String BUILD_TYPE = "debug";
    public static final String FLAVOR = "";
    public static final int VERSION_CODE = 1;
    public static final String VERSION_NAME = "1.0.0";
}
Run Code Online (Sandbox Code Playgroud)

通过python脚本或其他工具拆分所需的信息.这是一个例子:

import subprocess
#find your BuildConfig.java
_BuildConfig = subprocess.check_output('find {WORKSPACE} -name BuildConfig.java', shell=True).rstrip()
#get the version name
_Android_version = subprocess.check_output('grep -n "VERSION_NAME" '+_BuildConfig, shell=True).split('"')[1]
print('Android version :’+_Android_version)
Run Code Online (Sandbox Code Playgroud)

请原谅我有限的英语能力,但希望这会有所帮助.