非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
相关产品推荐
相关产品推荐

