MAUI项目在Android平台通过U盘实现软件更新
https://www.cnblogs.com/sesametech-dotnet/p/19674963
需求
项目使用MAUI开发的用Android工控机进行相关功能的实现。作为操作设备的屏幕嵌入到仪器中,要使用串口操作实现对仪器的控制。想要实现在有软件更新时,可以通过U盘实现对软件的升级。
功能实现
这里需要使用到 FileProvider,在Android 7之后出于安全考虑不再支持content://URL 或file:///URL这种文件访问方式。在Platforms/Android中主要添加/修改下面两个文件:
file_paths.xmlAndroidMainfest.xml

在Platforms/Android/Resources下面新建xml文件夹,并添加 provider_paths.xml文件。
| <paths xmlns:android="http://schemas.android.com/apk/res/android"> |
| <root-path name="root" path="" /> |
| <files-path name="files" path="" /> |
| <cache-path name="cache" path="" /> |
| <external-path name="camera_photos" path="" /> |
| <external-files-path name="external_file_path" path="" /> |
| <external-cache-path name="external_cache_path" path="" /> |
| </paths> |
修改Platforms/Android下面的AndroidManifest.xml文件,在application下添加provider,再添加一个安卓安装的权限
REQUEST_INSTALL_PACKAGES(安装应用)WRITE_EXTERNAL_STORAGE(写入外部存储中的文件)READ_EXTERNAL_STORAGE(读取外部存储中的文件)
AndroidManifest.xml文件内容如下:
| <manifest xmlns:android="http://schemas.android.com/apk/res/android"> |
| <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"> |
| <provider |
| android:name="androidx.core.content.FileProvider" |
| android:authorities="com.companyname.mauiupdateapp.fileprovider" |
| android:exported="false" |
| android:grantUriPermissions="true"> |
| <meta-data |
| android:name="android.support.FILE_PROVIDER_PATHS" |
| android:resource="@xml/file_paths" /> |
| </provider> |
| </application> |
| <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> |
| <uses-permission android:name="android.permission.INTERNET" /> |
| <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> |
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> |
| <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> |
| <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> |
| </manifest> |
在MainPage页面添加一个按钮用于实现软件安装功能,简化了项目实现,没有采用MVVM模式,直接通过Clicked事件实现软件安装。
| <Button |
| x:Name="UpdateBtn" |
| Clicked="OnCheckUpdateClicked" |
| HorizontalOptions="Fill" |
| Text="安装Apk" /> |
按钮事件实现:
| private async void OnCheckUpdateClicked(object? sender, EventArgs e) |
| { |
| await CheckForUpdates(); |
| } |
| private async Task CheckForUpdates() |
| { |
| try |
| { |
| UpdateBtn.IsEnabled = false; |
| await _updateService.InstallUpdateAsync(); |
| } |
| catch (Exception ex) |
| { |
| await DisplayAlertAsync("错误", $"异常: {ex.Message}", "确定"); |
| } |
| finally |
| { |
| UpdateBtn.IsEnabled = true; |
| } |
| } |
更新服务实现:
| public class UpdateService |
| { |
| public async Task InstallUpdateAsync() |
| { |
| // 调用平台特定的更新逻辑 |
| await UpdateHandlerFactory.Create().InstallUpdateAsync(); |
| } |
| } |
| public interface IUpdateHandler |
| { |
| Task InstallUpdateAsync(); |
| } |
| public static class UpdateHandlerFactory |
| { |
| public static IUpdateHandler Create() |
| { |
| return new MauiUpdateApp.Platforms.Android.UpdateHandler(); |
| return new DefaultUpdateHandler(); |
| } |
| } |
| public class DefaultUpdateHandler : IUpdateHandler |
| { |
| public async Task InstallUpdateAsync() |
| { |
| // 默认实现,非 Android 平台使用 |
| if (App.Current?.MainPage != null) |
| { |
| await App.Current.MainPage.DisplayAlertAsync("更新", "此平台不支持自动更新", "确定"); |
| } |
| } |
| } |
实现Android平台的安装Apk功能:
| using Android.Content; |
| using MauiUpdateApp.Services; |
| using Android.App; |
| namespace MauiUpdateApp.Platforms.Android; |
| public class UpdateHandler : IUpdateHandler |
| { |
| private static readonly HttpClient client = new HttpClient(); |
| public async Task InstallUpdateAsync() |
| { |
| try |
| { |
| var activity = Platform.CurrentActivity; |
| if (activity == null) |
| { |
| if (App.Current?.MainPage != null) |
| { |
| await App.Current.MainPage.DisplayAlertAsync("错误", "无法获取当前活动", "确定"); |
| } |
| return; |
| } |
| PickOptions options = new() { PickerTitle = "Please select a comic file", }; |
| var results = await FilePicker.Default.PickAsync(options); |
| if (results is null) |
| { |
| return; |
| } |
| // 安装 APK |
| InstallApk(results.FullPath, activity); |
| } |
| catch (Exception ex) |
| { |
| // 处理错误 |
| Console.WriteLine($"更新失败: {ex.Message}"); |
| if (App.Current?.MainPage != null) |
| { |
| await App.Current.MainPage.DisplayAlertAsync("错误", $"更新失败: {ex.Message}", "确定"); |
| } |
| } |
| } |
| private static void InstallApk(string apkPath, Activity? activity) |
| { |
| var file = new Java.IO.File(apkPath); |
| var uri = AndroidX.Core.Content.FileProvider.GetUriForFile(activity, $"{activity.PackageName}.fileprovider", file); |
| var intent = new Intent(Intent.ActionView); |
| intent.SetDataAndType(uri, "application/vnd.android.package-archive"); |
| intent.AddFlags(ActivityFlags.GrantReadUriPermission); |
| intent.AddFlags(ActivityFlags.NewTask); |
| activity.StartActivity(intent); |
| } |
| } |
以上为整个项目实现安装Apk的代码,想要获取源码的话,可以从
https://github.com/mzy666888/MauiUpdateApp中获取,欢迎给个Star
作者:芝麻麻雀
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。

浙公网安备 33010602011771号