MAUI项目在Android平台通过U盘实现软件更新
制。想要实现在有软件更新时,可以通过U盘实现对软件的升级。
·
制。想要实现在有软件更新时,可以通过U盘实现对软件的升级。
功能实现
这里需要使用到 FileProvider,在Android 7之后出于安全考虑不再支持content://URL 或file:///URL这种文件访问方式。在Platforms/Android中主要添加/修改下面两个文件:
file_paths.xmlAndroidMainfest.xml

在Platforms/Android/Resources下面新建xml文件夹,并添加 provider_paths.xml文件。
<?xml version="1.0" encoding="utf-8"?> |
|
<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文件内容如下:
<?xml version="1.0" encoding="utf-8"?> |
|
<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() |
|
{ |
|
#if ANDROID |
|
return new MauiUpdateApp.Platforms.Android.UpdateHandler(); |
|
#else |
|
return new DefaultUpdateHandler(); |
|
#endif |
|
} |
|
} |
|
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); |
|
} |
|
} |
更多推荐


所有评论(0)