以下是安卓App中调用升级接口并实现版本检查和升级功能的完整方案,包含网络请求、版本解析、下载安装等核心逻辑:
// CheckUpgradeResponse.java
public class CheckUpgradeResponse {
private int code;
private String msg;
private UpgradeData data;
private Map<String, Object> map;
// Getter/Setter
public int getCode() { return code; }
public UpgradeData getData() { return data; }
}
// UpgradeData.java
public class UpgradeData {
private int id;
private String version; // 版本号(如102000)
private String downloadUrl; // APK下载链接
private String updateDescription;// 更新说明
private long releaseTime; // 发布时间(时间戳)
// Getter/Setter
public String getVersion() { return version; }
public String getDownloadUrl() { return downloadUrl; }
}
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
}
// UpgradeApi.java
public interface UpgradeApi {
@GET("common/checkUpgrade")
Call<CheckUpgradeResponse> checkUpgrade();
}
// RetrofitClient.java
public class RetrofitClient {
private static final String BASE_URL = "http://127.0.0.1:8700/";
private static Retrofit retrofit;
public static Retrofit getClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
// UpgradeManager.java(封装升级逻辑)
public class UpgradeManager {
public void checkForUpdate(Context context) {
UpgradeApi api = RetrofitClient.getClient().create(UpgradeApi.class);
api.checkUpgrade().enqueue(new Callback<CheckUpgradeResponse>() {
@Override
public void onResponse(Call<CheckUpgradeResponse> call, Response<CheckUpgradeResponse> response) {
if (response.isSuccessful()) {
CheckUpgradeResponse result = response.body();
if (result != null && result.getCode() == 1) { // 成功码
UpgradeData newVersion = result.getData();
if (isNewVersionAvailable(newVersion.getVersion(), context)) {
showUpgradeDialog(context, newVersion);
}
}
}
}
@Override
public void onFailure(Call<CheckUpgradeResponse> call, Throwable t) {
// 网络请求失败处理
t.printStackTrace();
}
});
}
// 版本号比较(字符串转整数比较,适用于纯数字版本号)
private boolean isNewVersionAvailable(String newVersion, Context context) {
try {
int currentVersionCode = getCurrentVersionCode(context);
int newVersionCode = Integer.parseInt(newVersion);
return newVersionCode > currentVersionCode;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
// 获取当前App版本号(AndroidManifest中的versionCode)
private int getCurrentVersionCode(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(
context.getPackageName(), 0
);
return packageInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return 0;
}
}
}
private void showUpgradeDialog(Context context, UpgradeData data) {
new AlertDialog.Builder(context)
.setTitle("发现新版本")
.setMessage("版本号:" + data.getVersion() + "\n\n" + data.getUpdateDescription())
.setPositiveButton("立即升级", (dialog, which) -> startDownloadApk(context, data.getDownloadUrl()))
.setNegativeButton("稍后再说", null)
.show();
}
private void startDownloadApk(Context context, String url) {
new Thread(() -> {
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("下载失败");
// 保存APK到本地
String fileName = "app_" + System.currentTimeMillis() + ".apk";
String downloadPath = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS
).getPath() + File.separator + fileName;
FileOutputStream fos = new FileOutputStream(downloadPath);
InputStream is = response.body().byteStream();
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
fos.close();
is.close();
// 安装APK
installApk(context, new File(downloadPath));
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
// 安装APK(需处理Android 8.0+权限)
private void installApk(Context context, File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// 授予临时文件权限(通过FileProvider)
Uri apkUri = FileProvider.getUriForFile(context,
context.getPackageName() + ".fileprovider", file);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
}
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
provider>
<paths>
<external-path name="downloads" path="Download/" />
paths>
在App启动入口(如SplashActivity)或设置页面调用:
// 在SplashActivity的onCreate中
new UpgradeManager().checkForUpdate(this);
版本号类型:
version
是字符串(如"1.0.2"),需按分段比较:String[] currentParts = currentVersion.split("\\.");
String[] newParts = newVersion.split("\\.");
versionCode
(如102000),与Android原生versionCode
一致下载优化:
DownloadManager
替代手动文件流下载,支持断点续传和通知栏显示权限适配:
REQUEST_EXTERNAL_STORAGE
权限(或使用MediaStore
)WRITE_EXTERNAL_STORAGE
线程安全:
runOnUiThread()
处理通过以上实现,App可以完整实现从版本检查到下载安装的闭环,用户体验和兼容性得到有效保障。