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

How to get the build/version number of your Android application?

我需要弄清楚如何为我的Android应用程序获取或生成一个内部版本号。我需要在用户界面中显示内部版本号。

我需要和AndroidManifest.xml做些什么吗?


用途:

1
2
3
4
5
6
try {
    PackageInfo pInfo = context.getPackageManager().getPackageInfo(getPackageName(), 0);
    String version = pInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
    e.printStackTrace();
}

你可以通过这个得到版本代码

1
int verCode = pInfo.versionCode;


如果您使用的是Gradle插件/android studio,从0.7.0版开始,版本代码和版本名称在BuildConfig中静态可用。确保导入应用程序包,而不是其他BuildConfig

1
2
3
4
import com.yourpackage.BuildConfig;
...
int versionCode = BuildConfig.VERSION_CODE;
String versionName = BuildConfig.VERSION_NAME;

不需要上下文对象!

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

1
2
3
4
defaultConfig {
    versionCode 1
    versionName"1.0"
}


稍微短一点的版本,如果您只需要版本名。

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


您需要两个部分:Android:版本代码安卓:版本名

versioncode是一个数字,你提交到市场上的应用程序的每个版本都需要一个比上一个更高的数字。

versionname是一个字符串,可以是任何您想要的字符串。在这里,您将应用程序定义为"1.0"或"2.5"或"2 alpha extreme!"或者什么。

例子:

Kotlin:

1
2
3
4
5
6
7
8
val manager = this.packageManager
val info = manager.getPackageInfo(this.packageName, PackageManager.GET_ACTIVITIES)
toast("PackageName =" + info.packageName +"
VersionCode ="
            + info.versionCode +"
VersionName ="
            + info.versionName +"
Permissions =" + info.permissions)

爪哇:

1
2
3
4
5
6
7
8
9
PackageManager manager = this.getPackageManager();
PackageInfo info = manager.getPackageInfo(this.getPackageName(), PackageManager.GET_ACTIVITIES);
Toast.makeText(this,
    "PackageName =" + info.packageName +"
VersionCode ="
       + info.versionCode +"
VersionName ="
       + info.versionName +"
Permissions =" + info.permissions, Toast.LENGTH_SHORT).show();


使用Gradle和BuildConfig从buildconfig获取版本名

1
BuildConfig.VERSION_NAME

是的,现在很容易。

它是否返回版本名称的空字符串?

如果你得到的是一个空字符串,那么继续读下去。

我一直为BuildConfig.VERSION_NAME得到一个空字符串,因为我没有在我的等级构建文件中设置versionName(我从Ant迁移到Gradle)。因此,下面是确保通过Gradle设置VERSION_NAME的说明。

平地

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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}"
  }

}

注:这是杰克·沃顿的杰作。

AndroidManifest.xml中取出versionNameversionCode

既然你已经在build.gradle文件中设置了versionNameversionCode,那么你也可以从AndroidManifest.xml文件中删除它们(如果它们存在的话)。


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

我不认为需要从包经理那里得到它


这里是一个干净的解决方案,基于Scottyab的解决方案(由Xavi编辑)。它演示了如何首先获取上下文(如果您的方法没有提供上下文的话)。此外,它使用多行而不是每行调用多个方法。这使您在调试应用程序时更加容易。

1
2
3
4
5
6
7
8
9
10
11
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();
}

现在,您已经在字符串myVersionName中收到了版本名,您可以将其设置为textview或您喜欢的任何内容。

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


使用BuildConfig类

1
2
String versionName = BuildConfig.VERSION_NAME;
int versionCode = BuildConfig.VERSION_CODE;

build.gradle(应用程序)

1
2
3
4
5
6
7
 defaultConfig {
    applicationId"com.myapp"
    minSdkVersion 19
    targetSdkVersion 27
    versionCode 17
    versionName"1.0"
   }

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

在应用程序包中创建新类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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中,添加以下行:

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

在DeviceReady事件中,添加以下代码:

1
2
3
4
5
6
7
8
9
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属性:

1
2
3
4
5
6
7
8
window.plugins.packageManager.getVersionName(
    function(versionName) {
        //do something with versionName
    },
    function(errorMessage) {
        //do something with errorMessage
    }
);

源于这里和这里。


一个非常简单的方法是:

1
private String appVersion = BuildConfig.VERSION_NAME;

下面是获取版本名称和版本代码的简单方法

1
2
String version_name=BuildConfig.VERSION_NAME;
int version_code=BuildConfig.VERSION_CODE;


对于Xamarin用户,使用此代码获取版本名和代码

1)版本名称:

1
2
3
public string getVersionName(){
      return Application.Context.ApplicationContext.PackageManager.GetPackageInfo(Application.Context.ApplicationContext.PackageName, 0).VersionName;
}

2)版本代码:

1
2
3
public string getVersionCode(){
      return Application.Context.ApplicationContext.PackageManager.GetPackageInfo(Application.Context.ApplicationContext.PackageName, 0).VersionCode;
}

始终使用try catch块:

1
2
3
4
5
6
7
8
9
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());
}

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

1
2
3
4
5
6
7
8
9
10
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;
}


如果要在XML中使用它,请在渐变文件中添加以下行:

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

然后在XML上使用它,如下所示:

1
2
3
4
5
<TextView
        android:gravity="center_horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/versionName" />


我已经通过使用偏好类解决了这个问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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);
        }
    }
}

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

  • PackageManager获取版本。这是大多数情况下的最佳方法。
  • 1
    2
    3
    4
    5
    6
    try {
        String versionName = packageManager.getPackageInfo(packageName, 0).versionName;
        int versionCode = packageManager.getPackageInfo(packageName, 0).versionCode;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
  • 从生成的BuildConfig.java中获取。但请注意,如果您要在库中访问此值,它将返回使用此库的库版本,而不是AppsOne。所以只能在非图书馆项目中使用!
  • 1
    2
    String versionName = BuildConfig.VERSION_NAME;
    int versionCode = BuildConfig.VERSION_CODE;

    除了在图书馆项目中使用第二种方法之外,还有一些细节。在新的Android Gradle插件(3.0.0+)中,一些功能被删除。所以,现在,也就是说,为不同的口味设置不同的版本是不正确的。

    错误的方式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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
    }

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

    输出apk文件有一个解决方案集版本,手动:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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
        }
    }

    上面提到的代码是分块的,但这里又包括了所有代码。您需要一个try/catch块,因为它可能会引发"nameNotFoundException"。

    1
    2
    3
    try {
       String appVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
    } catch (PackageManager.NameNotFoundException e) {e.printStackTrace();}

    我希望这样可以简化一些事情。:)


    但是,一些不需要应用程序UI的buildconfig信息的人希望使用这些信息来设置CI作业配置,或者像我这样的其他人。

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

    工作区/build/generated/source/buildconfig/调试发布/包/buildconfig.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    /**
    * 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";
    }

    通过python脚本或其他工具拆分您需要的信息。下面是一个例子:

    1
    2
    3
    4
    5
    6
    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)

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


    不,您不需要对androidmanifest.xml做任何事情。

    基本上,您的应用程序的版本名称和版本代码位于应用程序级渐变文件中的defaultconfig标记下:

    1
    2
    3
    4
    defaultConfig {  
       versionCode 1  
       versionName"1.0"  
    }

    注意:当您希望在PlayStore中上载应用程序时,可以将任何名称作为版本名,但如果该应用程序已在PlayStore中,则版本代码必须与当前版本代码不同。

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

    1
    2
    3
    4
    5
    6
    7
    try {  
        PackageInfo pInfo =   context.getPackageManager().getPackageInfo(context.getPackageName(), 0);  
        String version = pInfo.versionName;  
        int verCode = pInfo.versionCode;  
    } catch (PackageManager.NameNotFoundException e) {  
        e.printStackTrace();  
    }

    试试这个:

    1
    2
    3
    4
    5
    6
    7
    8
    try
    {
        device_version =  getPackageManager().getPackageInfo("com.google.android.gms", 0).versionName;
    }
    catch (PackageManager.NameNotFoundException e)
    {
        e.printStackTrace();
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     package com.sqisland.android.versionview;

    import android.app.Activity;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.os.Bundle;
    import android.widget.TextView;

    public class MainActivity extends Activity {
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView textViewversionName = (TextView) findViewById(R.id.text);

        try {
            PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
            textViewversionName.setText(packageInfo.versionName);

        }
        catch (PackageManager.NameNotFoundException e) {

        }

      }
    }


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    private String GetAppVersion(){
            try {
                PackageInfo _info = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0);
                return _info.versionName;
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
                return"";
            }
        }

        private int GetVersionCode(){
            try {
                PackageInfo _info = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0);
                return _info.versionCode;
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
                return -1;
            }
        }

    第一:

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

    然后用这个:

    1
    2
    3
    4
    5
    6
    7
    PackageInfo pInfo = null;
    try {
         pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
    } catch (NameNotFoundException e) {
         e.printStackTrace();
                }
    String versionName = pInfo.versionName;


    内部片段使用示例。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
            import android.content.pm.PackageManager;
            .......

            private String VersionName;
            private String VersionCode;
            .......


            Context context = getActivity().getApplicationContext();

            /*Getting Application Version Name and Code*/
            try
            {

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

                 /*I find usefull to convert vervion code into String, so it's ready for TextViev/server side checks*/

                 VersionCode = Integer.toString(context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode);
            } catch (PackageManager.NameNotFoundException e)
            {
                 e.printStackTrace();
            }

    // DO SOMETHING USEFULL WITH THAT


    对于api 28,packageinfo.versioncode已弃用,请使用以下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        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";
        }

    1
    2
    3
    4
    5
    6
    7
    8
      PackageInfo pinfo = null;
        try {
            pinfo = getPackageManager().getPackageInfo(getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        int versionNumber = pinfo.versionCode;
        String versionName = pinfo.versionName;

    因为我只需要获取版本代码并检查应用程序是否更新,如果更新了,我必须启动PlayStore才能获得更新。我是这样做的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public class CheckForUpdate {

    public static final String ACTION_APP_VERSION_CHECK="app-version-check";

    public static void launchPlayStoreApp(Context context)
    {

        final String appPackageName = context.getPackageName(); // getPackageName() from Context or Activity object
        try {
            context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName)));
        } catch (android.content.ActivityNotFoundException anfe) {
            context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
        }

    }

    public static int getRemoteVersionNumber(Context context)
    {
        int versionCode=0;
        try {
            PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            String version = pInfo.versionName;
            versionCode=pInfo.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return versionCode;
    }

    }

    然后,我通过创建一个Util类,使用共享首选项保存了版本代码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    public class PreferenceUtils {

    // this is for version code
    private  final String APP_VERSION_CODE ="APP_VERSION_CODE";
    private  SharedPreferences sharedPreferencesAppVersionCode;
    private SharedPreferences.Editor editorAppVersionCode;
    private static Context mContext;

    public PreferenceUtils(Context context)
    {
        this.mContext=context;
        // this is for app versioncode
        sharedPreferencesAppVersionCode=mContext.getSharedPreferences(APP_VERSION_CODE,MODE_PRIVATE);
        editorAppVersionCode=sharedPreferencesAppVersionCode.edit();
    }

    public void createAppVersionCode(int versionCode) {

        editorAppVersionCode.putInt(APP_VERSION_CODE, versionCode);
        editorAppVersionCode.apply();
    }

    public int getAppVersionCode()
    {
        return sharedPreferencesAppVersionCode.getInt(APP_VERSION_CODE,0); // as default  version code is 0
         }
       }

    1
    2
    3
    4
    5
    6
    7
    8
    try {
            PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
            String versionName = packageInfo.versionName;
            int versionCode = packageInfo.versionCode;
            //binding.tvVersionCode.setText("v" + packageInfo.versionName);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }