安卓App中调用升级接口并实现版本检查和升级功能的完整方案

以下是安卓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; }
}

二、网络请求实现(使用Retrofit)

1. 添加依赖(build.gradle)
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'
}
2. 创建API接口
// UpgradeApi.java
public interface UpgradeApi {
    @GET("common/checkUpgrade")
    Call<CheckUpgradeResponse> checkUpgrade();
}
3. 初始化Retrofit
// 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;
    }
}

三、版本检查逻辑

1. 在Activity/Fragment中调用接口
// 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;
        }
    }
}

四、升级对话框与下载逻辑

1. 显示升级弹窗
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();
}
2. 下载并安装APK(使用OkHttp)
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);
}

五、配置文件与权限

1. AndroidManifest.xml添加权限

<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>
2. 添加file_paths.xml(res/xml/)

<paths>
    <external-path name="downloads" path="Download/" />
paths>

六、调用升级检查

在App启动入口(如SplashActivity)或设置页面调用:

// 在SplashActivity的onCreate中
new UpgradeManager().checkForUpdate(this);

关键注意事项:

  1. 版本号类型

    • 若接口返回的version是字符串(如"1.0.2"),需按分段比较:
      String[] currentParts = currentVersion.split("\\.");
      String[] newParts = newVersion.split("\\.");
      
    • 建议后端返回整数型versionCode(如102000),与Android原生versionCode一致
  2. 下载优化

    • 使用DownloadManager替代手动文件流下载,支持断点续传和通知栏显示
    • 大文件下载需在后台服务中进行,避免Activity销毁导致下载中断
  3. 权限适配

    • Android 10+推荐使用REQUEST_EXTERNAL_STORAGE权限(或使用MediaStore
    • 动态权限申请需在下载前检查并请求WRITE_EXTERNAL_STORAGE
  4. 线程安全

    • 网络请求和文件操作需在子线程执行,UI更新通过runOnUiThread()处理

通过以上实现,App可以完整实现从版本检查到下载安装的闭环,用户体验和兼容性得到有效保障。

你可能感兴趣的:(Android,android)