ChatGPT:请帮我写一个Android下自动更新的DEMO

这里是一个简单的Android自动更新的demo:

首先,在你的App的build.gradle文件中加入以下代码段以添加依赖:

dependencies {
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'com.google.code.gson:gson:2.8.6'
    implementation 'com.squareup.okhttp3:okhttp:4.9.0'
}

然后创建更新类,如下:

public class UpdateHelper {
    private static final String UPDATE_URL = "https://your-update-url.com";
    private static final String TAG = UpdateHelper.class.getSimpleName();

    private Context mContext;
    private PackageManager mPackageManager;
    private AlertDialog mAlertDialog;

    public UpdateHelper(Context context) {
        mContext = context;
        mPackageManager = context.getPackageManager();
    }

    public void checkForUpdates() {
        final OkHttpClient client = new OkHttpClient.Builder().build();
        final Gson gson = new Gson();

        final Request request = new Request.Builder()
                .url(UPDATE_URL)
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e(TAG, "Error checking for updates", e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    final String responseBody = response.body().string();
                    final UpdateInfo updateInfo = gson.fromJson(responseBody, UpdateInfo.class);

                    if (updateInfo.isNewerVersionAvailable(getCurrentVersionName())) {
                        showUpdateDialog(updateInfo);
                    }
                }
            }
        });
    }

    private String getCurrentVersionName() {
        String versionName;
        try {
            versionName = mPackageManager.getPackageInfo(mContext.getPackageName(), 0).versionName;
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "Error getting version name", e);
            versionName = "";
        }
        return versionName;
    }

    private void showUpdateDialog(final UpdateInfo updateInfo) {
        mAlertDialog = new AlertDialog.Builder(mContext)
                .setTitle(updateInfo.getTitle())
                .setMessage(updateInfo.getMessage())
                .setPositiveButton("Update", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        startDownload(updateInfo.getApkUrl());
                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mAlertDialog.dismiss();
                    }
                })
                .show();
    }

    private void startDownload(String apkUrl) {
        final DownloadManager downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);

        final DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl))
                .setTitle("App Update")
                .setDescription("Downloading update...")
                .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                .setAllowedOverMetered(true);

        final long downloadId = downloadManager.enqueue(request);

        final BroadcastReceiver downloadCompleteBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);

                if (downloadId == id) {
                    installApk(context, downloadManager.getUriForDownloadedFile(downloadId));
                    context.unregisterReceiver(this);
                }
            }
        };

        mContext.registerReceiver(downloadCompleteBroadcastReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

    private void installApk(Context context, Uri uri) {
        final Intent intent = new Intent(Intent.ACTION_VIEW)
                .setDataAndType(uri, "application/vnd.android.package-archive")
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        context.startActivity(intent);
    }
}

这个类会发送一个HttpGet请求到指定的URL(UPDATE_URL)并解析Json响应以获得应用程序的更新信息。如果有新版本的应用程序可用,将显示一个对话框,提醒用户进行下载。当下载完成后,将在浏览器中打开新的APK文件以启动安装程序。

在你的Activity中调用它,如下:

final UpdateHelper updateHelper = new UpdateHelper(this);
updateHelper.checkForUpdates();

这就是一个简单的自动更新示例,需要根据自己的需求做相应调整。

以下是一个在Android 10下实现静默更新安装的demo:

  1. 在AndroidManifest.xml文件中添加以下权限:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
  1. 创建一个BroadcastReceiver类,用于接收应用下载完成的广播:
public class MyInstallReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            // Android 8.0以下版本使用普通安装
            String apkFilePath = Environment.getExternalStorageDirectory().getPath() + "/myapp.apk";
            Intent installIntent = new Intent(Intent.ACTION_VIEW);
            installIntent.setDataAndType(Uri.fromFile(new File(apkFilePath)), "application/vnd.android.package-archive");
            installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(installIntent);
        } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            // Android 8.0~Android 9.0版本使用未知来源应用安装
            Uri apkUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileprovider", new File(context.getExternalCacheDir(), "myapp.apk"));
            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);
        } else {
            // Android 10及以上版本使用静默安装
            installApk(context, new File(context.getExternalCacheDir(), "myapp.apk"));
        }
    }

    private void installApk(Context context, File apkFile) {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                // Android 10及以上版本先使用PackageManager.newInstallSession来创建一个安装Session
                PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
                PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(
                        PackageInstaller.SessionParams.MODE_FULL_INSTALL);
                int sessionId = packageInstaller.createSession(sessionParams);
                PackageInstaller.Session session = packageInstaller.openSession(sessionId);
                OutputStream out = session.openWrite("myapp", 0, apkFile.length());
                FileInputStream fis = new FileInputStream(apkFile);
                byte[] buffer = new byte[65536];
                int n;
                while ((n = fis.read(buffer)) > 0) {
                    out.write(buffer, 0, n);
                }
                out.close();
                session.commit(createIntentSender(context, sessionId));
                fis.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private IntentSender createIntentSender(Context context, int sessionId) {
        Intent intent = new Intent(context, MyInstallReceiver.class);
        intent.setAction("android.intent.action.MY_PACKAGE_INSTALL");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
        return pendingIntent.getIntentSender();
    }
}
  1. 在AndroidManifest.xml文件中注册BroadcastReceiver:
<receiver
    android:name=".MyInstallReceiver"
    android:enabled="true"
    android:exported="false">
    <intent-filter>
        <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
        <action android:name="android.intent.action.MY_PACKAGE_INSTALL" />
    </intent-filter>
</receiver>
  1. 在应用代码中下载apk文件并触发安装:
private void downloadAndInstallApk() {
    // 下载apk文件
    DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
    DownloadManager.Request request = new DownloadManager.Request(Uri.parse("apk文件下载链接"));
    request.setTitle("myapp");
    request.setDestinationInExternalCacheDir(this, "myapp.apk");
    long downloadId = downloadManager.enqueue(request);
    // 监听下载完成的广播,触发安装
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
    registerReceiver(new MyInstallReceiver(), intentFilter);
}

这样就可以在Android 10下实现静默更新安装了。需要注意的是,静默安装需要先向用户请求安装权限,且无法给出安装结果的提示,所以应该在开发过程中仔细测试。