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


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

我必须做些什么 AndroidManifest.xml


956
2018-01-06 14:43


起源


不确定,但我认为你可以通过解析AndroidManifest.xml文件来获得它。 - Sunit Kumar Gupta
复制: stackoverflow.com/questions/4471025/... - Marcelo Filho
请指出正确的答案。 - salman


答案:


使用:

try {
    PackageInfo pInfo = this.getPackageManager().getPackageInfo(getPackageName(), 0);
    String version = pInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
    e.printStackTrace();
}

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

int verCode = pInfo.versionCode;

1780
2017-07-06 08:54



@Felix你不能在上下文之外调用getPackageManager(),因此可能需要getApplicationContext()(或传递上下文)。 - Sver
如果您在某些静态方法中需要此数字而无法传递上下文,该怎么办?我的设计不好? - Gubatron
别忘了 try... catch.. 什么时候 getPackageInfo() - anticafe
@Gubatron我在下面的回答允许静态检索这些值。 - Sam Dozor
如果你只想获得应用程序的版本,这是两个复杂的。你应该用 BuildConfig.VERSION_** 如建议 这里。 - Timo Bähr


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

import com.yourpackage.BuildConfig;
...
int versionCode = BuildConfig.VERSION_CODE;
String versionName = BuildConfig.VERSION_NAME;

不需要Context对象!

还要确保在你的指定中指定它们 build.gradle 文件而不是 AndroidManifest.xml

defaultConfig {
    versionCode 1
    versionName "1.0"
}

1450
2018-01-14 16:45



这实际上比所有上下文和包管理器好很多,谢谢。 - superjugy
实际上这是Android Studio推出后的最佳解决方案! +1来自我的身边 - Dhruvil Patel
它不太可靠。版本名称大多数时间显示为空字符串。 - Binoy Babu
@BinoyBabu如果你指定了它,它永远不应该显示为空字符串 versionName 为您的应用程序 build.gradle 文件。 - Sam Dozor
您需要导入正确的包才能使用: import com.yourapppackage.android.BuildConfig - Eric B.


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

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

402
2018-04-26 10:22



优秀。对于NameNotFoundException,这应该被try / catch包围。 - Igor Ganapolsky
+1我已经实施了你的解决方案,效果很好!但是,这个解决方案应该被try和catch包围,就像Igor所说的那样,将每个方法调用放在一个单独的行而不是调用context.methodName()。subMethod()。anotherSubMethod()等是很好的做法(例如用于调试)。在一条线上。因此我提供了更清洁的解决方案 下面 - Michael
这是正确的解决方案,谢谢;)但是,正如@IgorGanapolsky所建议的那样,它需要被try / catch包围:) - andrea.rinaldi
对于那些使用Gradle的人 - 有一个更简单的解决方案。请参阅下面的答案。 - Sam Dozor
@Erwinus我全心全意地不同意使用通用Exception来捕捉这样的东西的想法。更细粒度的异常表明开发人员对可能的错误的理解。 - Igor Ganapolsky


使用Gradle和BuildConfig

从BuildConfig获取VERSION_NAME

BuildConfig.VERSION_NAME

是的,现在就这么简单。

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

如果你得到一个空字符串 BuildConfig.VERSION_NAME 继续读下去。

我一直得到一个空字符串 BuildConfig.VERSION_NAME 因为我没有设置 versionName 在我的成绩构建文件中(我从ANT迁移到Gradle)。所以,这里有说明,以确保您正在设置您的 VERSION_NAME 通过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}"
  }

}

注意:这是来自高手 杰克沃顿

删除 versionName 和 versionCode 从 AndroidManifest.xml

既然你已经设定了 versionName 和 versionCode 在里面 build.gradle 现在文件,您也可以从您的文件中删除它们 AndroidManifest.xml 文件,如果他们在那里。


125
2018-02-05 19:13



只要您从应用程序项目访问BuildConfig,而不是应用程序项目中使用的库,这就很有效。否则,您将获得库项目的BuildConfig,而不是应用程序。 - John Cummings
@JohnCummings有趣......没想到。 - Joshua Pinter
根本不工作, versionName "1.2",和 BuildConfig.VERSION_NAME 返回 empty。 API> 21 - Sojtin
@Sojtin你有没有工作? - Joshua Pinter
作为后续,我们实际上停止使用这种方法,只支持静态整数和静态字符串 versionCode 和 versionName, 分别。只是因为像Code Push这样的工具试图通过解析你的版本来获得你的版本号 build.gradle 文件,他们不能充满动态值。 - Joshua Pinter


您需要两个部分: 安卓的versionCode 安卓的versionName

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

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

例:

要在代码中访问它,请执行以下操作:

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

123
2018-02-08 04:31



Android官方介绍 android:versionCode 和 android:versionName 可以在这里找到: developer.android.com/tools/publishing/... - Jeffro
这个 在这种情况下是Context .ie Activity,Service .etc - peter
当你粘贴一些示例代码是有用的解释参数的含义....但是每个人都可以理解什么 this.getPackageName() 代表着 0 你吐的就没有关于含义的线索了 - Rafael Lima


BuildConfig.VERSION_NAME //version name from your build file
BuildConfig.VERSION_CODE //version code from your build file

我没有看到需要从包管理器获取它


55
2018-01-29 04:05



如果您正在编写库,则无法访问客户端“BuildConfig”,您必须从其他位置获取该库。 - yshahak


这里有一个 清洁解决方案,基于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();
}

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

// set version name to a TextView
TextView tvVersionName = (TextView) findViewById(R.id.tv_versionName);
tvVersionName.setText(myVersionName);

50
2017-08-21 08:54



唯一正确的解决方案。 - Fattie
非常感谢! - brainvision
你认为NNFE真的会被扔掉吗?在包管理器中找不到正在运行的应用程序会很奇怪:) - TWiStErRob
我和你在一起它可能很奇怪,但它是这种方法的默认例外 - 请参阅 API: 它说 Throws PackageManager.NameNotFoundException if a package with the given name can not be found on the system.。但是,我无法想象这样的场景! - Michael


如果您正在使用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;
    }
}

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

<plugin name="PackageManagerPlugin" value="com.Demo.PackageManagerPlugin" />

在你的 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());
});

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

window.plugins.packageManager.getVersionName(
    function(versionName) {
        //do something with versionName
    },
    function(errorMessage) {
        //do something with errorMessage
    }
);

源自 这里 和 这里


23
2018-03-12 21:50



问题不在于PhoneGap。你的回答可能会让人感到困惑。 - likebobby
@BobbyJ在问题,标题或标签中没有指明问题是关于本机应用程序的。这是谷歌在我寻找答案时提出来的,并且会让我节省几个小时。 - Sean Hall
谢谢Hall72215。我会很高兴这个...如果真的没有其他办法来获得你自己的版本号?如果可能的话我宁愿避免使用插件! - Magnus Smith
@MagnusSmith除非PhoneGap / Cordova将其添加到内置函数中,否则不会。 - Sean Hall
在此示例中,您可以看到使用第三方解决方案创建应用程序有多么愚蠢。当你自己从头开始编写它时,它只需要几行代码。 - Codebeat


一个非常简单的方法是:

private String appVersion = BuildConfig.VERSION_NAME;

20
2018-01-20 13:55





总是这样做 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());
}

8
2018-05-28 06:43