You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非Google Play渠道Android应用内更新:监听未触发问题求助

问题根源说明

你当前使用的AppUpdateManager是Google Play Core库的专属组件,完全依赖Google Play商店生态——只有当应用上架Play商店,且后台配置了对应更新包时,getAppUpdateInfo()才会返回有效数据并触发成功监听。你的应用未上架Play商店,这套逻辑从根本上不适用。

自有服务器更新功能的正确实现方案

以下是基于自有服务器的完整更新流程实现:

一、服务器端准备

需要提供一个接口,返回应用的最新版本信息,格式建议用JSON:

{
  "latestVersionCode": 2,
  "latestVersionName": "1.1.0",
  "downloadUrl": "http://your-server.com/app/update/v2/app-release.apk",
  "updateDesc": "修复支付bug,新增扫码功能"
}

二、Android端实现步骤

1. 获取当前应用版本信息

通过PackageManager获取本地应用的版本号和版本名称:

private long getCurrentVersionCode() {
    try {
        PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? packageInfo.getLongVersionCode() : packageInfo.versionCode;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return 0;
    }
}

private String getCurrentVersionName() {
    try {
        PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
        return packageInfo.versionName;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return "";
    }
}

2. 请求服务器版本接口并对比

用OkHttp/Retrofit发起网络请求(必须在子线程执行,避免ANR),对比本地与服务器版本号:

// 定义版本信息实体类
static class VersionInfo {
    private int latestVersionCode;
    private String latestVersionName;
    private String downloadUrl;
    private String updateDesc;

    // Getter方法
    public int getLatestVersionCode() { return latestVersionCode; }
    public String getLatestVersionName() { return latestVersionName; }
    public String getDownloadUrl() { return downloadUrl; }
    public String getUpdateDesc() { return updateDesc; }
}

private void checkForUpdate() {
    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
            .url("http://your-server.com/api/app/version")
            .build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();
            runOnUiThread(() -> Toast.makeText(MainActivity.this, "检查更新失败", Toast.LENGTH_SHORT).show());
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (response.isSuccessful() && response.body() != null) {
                String json = response.body().string();
                VersionInfo versionInfo = new Gson().fromJson(json, VersionInfo.class);

                // 对比版本号,判断是否需要更新
                if (versionInfo.getLatestVersionCode() > getCurrentVersionCode()) {
                    runOnUiThread(() -> showUpdateDialog(versionInfo));
                }
            }
        }
    });
}

3. 弹出更新提示对话框

替换原有弹窗逻辑,使用自有服务器的更新信息:

private void showUpdateDialog(VersionInfo versionInfo) {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("发现新版本 v" + versionInfo.getLatestVersionName());
    builder.setMessage(versionInfo.getUpdateDesc());
    builder.setPositiveButton("立即更新", (dialog, which) -> startDownload(versionInfo.getDownloadUrl()));
    builder.setNegativeButton("稍后再说", null);
    // 若需强制更新,可设置setCancelable(false)并隐藏取消按钮
    builder.show();
}

4. 实现APK下载与安装

使用系统DownloadManager处理下载,适配不同Android版本的安装权限:

private void startDownload(String downloadUrl) {
    // Android 8.0+ 需检查未知来源安装权限
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        if (!getPackageManager().canRequestPackageInstalls()) {
            startActivityForResult(
                new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:" + getPackageName())),
                1001
            );
            return;
        }
    }

    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl));
    request.setTitle("应用更新");
    request.setDescription("正在下载最新版本");
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "app-update.apk");

    DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
    if (downloadManager != null) {
        long downloadId = downloadManager.enqueue(request);
        // 注册广播监听下载完成事件
        registerReceiver(new DownloadCompleteReceiver(downloadId), new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }
}

// 下载完成广播接收器
class DownloadCompleteReceiver extends BroadcastReceiver {
    private final long downloadId;

    public DownloadCompleteReceiver(long downloadId) {
        this.downloadId = downloadId;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
        if (id == downloadId) {
            DownloadManager downloadManager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
            if (downloadManager != null) {
                Uri apkUri = downloadManager.getUriForDownloadedFile(id);
                if (apkUri != null) {
                    Intent installIntent = new Intent(Intent.ACTION_VIEW);
                    installIntent.setDataAndType(apkUri, "application/vnd.android.package-archive");
                    installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    context.startActivity(installIntent);
                }
            }
            context.unregisterReceiver(this);
        }
    }
}

5. 添加必要权限

在AndroidManifest.xml中声明:

<!-- 网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Android 10以下存储权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
<!-- Android 8.0+ 未知来源安装权限 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

三、最终调用

在onCreate方法中替换原有AppUpdateManager相关代码,调用自定义的更新检查方法:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 替换原有AppUpdateManager逻辑
    checkForUpdate();

    // 保留原有其他业务代码
    mIntentFilter = new IntentFilter();
    mIntentFilter.addAction(mBroadcastStringAction);
    mIntentFilter.addAction(mBroadcastIntegerAction);
    mIntentFilter.addAction(mBroadcastArrayListAction);
    mIntentFilter.addAction(mBroadcastBooleanAction);

    Intent serviceIntent = new Intent(this, InternetConnectionBackgroundService.class);
    startService(serviceIntent);

    Intent intent = new Intent(this, CommonBoundService.class);
    bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

    PrinterService.getInstance().initSunmiPrinterService(this);

    mainActivityViewModel = ViewModelProviders.of(this).get(MainActivityViewModel.class);
}

内容的提问来源于stack exchange,提问作者Ibanez1408

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 05:15:47