我需要弄清楚如何获取或制作Android应用程序的版本号。我需要在UI中显示内部版本号。
我必须使用AndroidManifest.xml吗?
我需要弄清楚如何获取或制作Android应用程序的版本号。我需要在UI中显示内部版本号。
我必须使用AndroidManifest.xml吗?
您需要两个部分:
android:版本代码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)
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();
如果您只需要版本名称,请稍微缩短版本。
try{
String versionName = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0).versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
Use:
try {
PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
String version = pInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
您可以使用以下命令获取版本代码
int verCode = pInfo.versionCode;
如果您使用的是PhoneGap,请创建自定义PhoneGa插件:
在应用程序包中创建新类:
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
}
);
源自这里和这里。
这是一个干净的解决方案,基于scottyab(由哈维编辑)的解决方案。它显示了如果方法没有提供上下文,如何首先获取上下文。此外,它使用多行而不是每行调用多个方法。这使您在调试应用程序时更容易。
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();
}
现在您在StringmyVersionName中收到了版本名,您可以将其设置为TextView或任何您喜欢的内容。。
// Set the version name to a TextView
TextView tvVersionName = (TextView) findViewById(R.id.tv_versionName);
tvVersionName.setText(myVersionName);
如果您使用Gradle插件/AndroidStudio,从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"
}
始终使用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());
}
使用Gradle和BuildConfig
从BuildConfig获取VERSION_NAME
BuildConfig.VERSION_NAME
是的,现在就这么简单了。
它是否返回VERSION_NAME的空字符串?
如果您正在获取BuildConfig.VERSION_NAME的空字符串,请继续阅读。
我一直得到BuildConfig.VERSION_NAME的空字符串,因为我没有在Grade构建文件中设置versionName(我从Ant迁移到Gradle)。因此,以下是确保您通过Gradle设置VERSION_NAME的说明。
文件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}"
}
}
注:这是大师杰克·沃顿的作品。
从AndroidManifest.xml中删除versionName和versionCode
而且,既然您现在已经在build.gradle文件中设置了versionName和versionCode,那么您也可以将它们从AndroidManifest.xml文件中删除(如果有的话)。
第一:
import android.content.pm.PackageManager.NameNotFoundException;
然后使用这个:
PackageInfo pInfo = null;
try {
pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
}
catch (NameNotFoundException e) {
e.printStackTrace();
}
String versionName = pInfo.versionName;
我已经通过使用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);
}
}
}
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) {
}
}
}
对于不需要应用程序UI的BuildConfig信息,但希望使用此信息设置CI作业配置或其他信息的人,如我:
只要成功构建项目,项目目录下就会有一个自动生成的文件BuildConfig.java。
{WORKSPACE}/build/generated/source/buildConfig/{debug|release}/{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";
}
通过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)
如果要在XML内容上使用它,请在Gradle文件中添加以下行:
applicationVariants.all { variant ->
variant.resValue "string", "versionName", variant.versionName
}
然后将其用于XML内容,如下所示:
<TextView
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/versionName" />
以下是获取版本代码的方法:
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;
}
对于Xamarin用户,使用此代码获取版本名称和代码
版本名称:公共字符串getVersionName(){return Application.Context.ApplicationContext.BackageManager.GetPackageInfo(Application.Context.ApplicationContext.PackageName,0).VersionName;}版本代码:公共字符串getVersionCode(){return Application.Context.ApplicationContext.BackageManager.GetPackageInfo(Application.Context.ApplicationContext.PackageName,0).VersionCode;}
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;
}
}
试试这个:
try
{
device_version = getPackageManager().getPackageInfo("com.google.android.gms", 0).versionName;
}
catch (PackageManager.NameNotFoundException e)
{
e.printStackTrace();
}
这段代码在上面提到过,但在这里,它再次全部包含在内。您需要try/catch块,因为它可能引发“NameNotFoundException”。
try {
String appVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
}
catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
我希望这能为将来的人简化事情
内部片段用法示例。
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 it useful 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 useful with that
有一些方法可以通过编程方式获取versionCode和versionName。
从PackageManager获取版本。这是大多数情况下的最佳方式。尝试{字符串versionName=packageManager.getPackageInfo(packageName,0).versionName;int versionCode=packageManager.getPackageInfo(packageName,0).versionCode;}catch(PackageManager.NameNotFoundException e){e.printStackTrace();}从生成的BuildConfig.java中获取它。但请注意,如果您在库中访问此值,它将返回使用此库的库版本,而不是应用程序版本。所以只能在非库项目中使用!字符串版本名称=BuildConfig.VERSION_NAME;int versionCode=BuildConfig.VERSION_CODE;
除了在库项目中使用第二种方式之外,还有一些细节。在新的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
}
上面的代码将正确设置BuildConfig中的值,但如果您没有在默认配置中设置版本,则从PackageManager中您将收到0和null。因此,您的应用程序将在设备上具有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
}
}
PackageInfo pinfo = null;
try {
pinfo = getPackageManager().getPackageInfo(getPackageName(), 0);
}
catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
int versionNumber = pinfo.versionCode;
String versionName = pinfo.versionName;
使用BuildConfig类:
String versionName = BuildConfig.VERSION_NAME;
int versionCode = BuildConfig.VERSION_CODE;
文件build.gradle(应用程序)
defaultConfig {
applicationId "com.myapp"
minSdkVersion 19
targetSdkVersion 27
versionCode 17
versionName "1.0"
}
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();
}
由于我只需要获取版本代码并检查应用程序是否更新,如果是,我必须启动play商店以获取更新的应用程序。我是这样做的。
public class CheckForUpdate {
public static final String ACTION_APP_VERSION_CHECK = "app-version-check";
public static void launchPlayStoreApp(Context context)
{
// getPackageName() from Context or Activity object
final String appPackageName = context.getPackageName();
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类,使用共享首选项保存了版本代码。
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 the 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 the default version code is 0
}
}
不,您不需要对AndroidManifest.xml执行任何操作
基本上,应用程序的版本名称和版本代码位于应用程序级Gradle文件中的defaultConfig标记下:
defaultConfig {
versionCode 1
versionName "1.0"
}
注意:当您希望将应用程序上载到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();
}
对于API 28(Android 9(Pie)),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";
}
使用以下方法获取应用程序版本或内部版本代码,该代码用于通过APK文件的版本代码识别APK文件。版本代码用于检测更新、发布等时的实际构建配置。
int versionCode = BuildConfig.VERSION_CODE;
版本名称用于显示开发序列的用户或开发人员。您可以根据需要添加任何类型的版本名称。
String versionName = BuildConfig.VERSION_NAME;
对构建系统有用:有一个用APK文件生成的文件,名为output.json,其中包含每个生成的APK文件的一系列信息,包括versionName和versionCode。
例如
[
{
"apkInfo": {
"baseName": "x86-release",
"enabled": true,
"filterName": "x86",
"fullName": "86Release",
"outputFile": "x86-release-1.0.apk",
"splits": [
{
"filterType": "ABI",
"value": "x86"
}
],
"type": "FULL_SPLIT",
"versionCode": 42,
"versionName": "1.0"
},
"outputType": {
"type": "APK"
},
"path": "app-x86-release-1.0.apk",
"properties": {}
}
]
与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
}
Kotlin示例:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.act_signin)
packageManager.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES).apply {
findViewById<TextView>(R.id.text_version_name).text = versionName
findViewById<TextView>(R.id.text_version_code).text =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) "$longVersionCode" else "$versionCode"
}
packageManager.getApplicationInfo(packageName, 0).apply{
findViewById<TextView>(R.id.text_build_date).text =
SimpleDateFormat("yy-MM-dd hh:mm").format(java.io.File(sourceDir).lastModified())
}
}
Kotlin单层
val versionCode = BuildConfig.VERSION_CODE
val versionName = BuildConfig.VERSION_NAME
Java一行程序
String versionCode = String.valueOf(BuildConfig.VERSION_CODE);
String versionName = String.valueOf(BuildConfig.VERSION_NAME);
确保将BuildConfig导入到类中。
在这个问题中有两种不同的情况,在任何答案中都没有得到正确的解决。
场景1:您没有使用模块
如果您没有使用模块,则可以访问BuildConfig文件,并立即使用以下命令获取版本代码:
val versionCode = BuildConfig.VERSION_CODE
这是有效的,因为这是应用程序级别的BuildConfig文件,因此它将包含对应用程序版本代码的引用
场景2:您的应用程序有许多模块,您假装从模块层次结构中的较低模块访问应用程序版本代码
对于您来说,有许多具有给定层次结构的模块是正常的,例如app->data->domain->ui等。在这种情况下,如果您从“ui”模块访问BuildConfig文件,它将不会向您提供应用程序版本代码的引用,而是该模块的版本代码。
为了获得应用程序版本代码,您可以使用给定的kotlin扩展函数:
fun Activity.getVersionCode(): Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
packageManager.getPackageInfo(packageName, 0).longVersionCode.toInt()
} else {
packageManager.getPackageInfo(packageName, 0).versionCode
}
版本名称的方法类似:
fun Activity.getVersionName(): String = try {
packageManager?.getPackageInfo(packageName, 0)?.versionName ?: ""
} catch (e: PackageManager.NameNotFoundException) {
""
}
就写这个。
XML代码
<TextView
android:id="@+id/appversion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
初始化textview的变量
TextView appversion;
将textview id设置为变量
appversion = findViewById(R.id.appversion);
这是显示应用程序版本BuildConfig.version_NAME的主要代码,仅将其用作字符串值
textview.setText("v"+BuildConfig.VERSION_NAME);
非常简单:
val manufacturer = Build.MANUFACTURER
val model = Build.MODEL
val version = Build.VERSION.SDK_INT
val versionRelease = Build.VERSION.RELEASE
Log.e("TAG","VERSION.RELEASE {" + Build.VERSION.RELEASE + "}");
Log.e("TAG","\nVERSION.INCREMENTAL {" + Build.VERSION.INCREMENTAL + "}");
Log.e("TAG","\nVERSION.SDK {" + Build.VERSION.SDK + "}");
Log.e("TAG","\nBOARD {" + Build.BOARD + "}");
Log.e("TAG","\nBRAND {" + Build.BRAND + "}");
Log.e("TAG","\nDEVICE {" + Build.DEVICE + "}");
Log.e("TAG","\nFINGERPRINT {" + Build.FINGERPRINT + "}");
Log.e("TAG","\nHOST {" + Build.HOST + "}");
Log.e("TAG","\nID {" + Build.ID + "}");
幸亏https://stackoverflow.com/a/40421709/2828651