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

如何通过Xamarin Forms实现APK自动安装?

搞定Xamarin.Forms Android APK自动安装的方案

嘿,我来帮你解决这个自动安装APK的问题!首先得明确:Android系统出于安全考虑,普通第三方应用无法完全绕过用户交互实现100%自动安装,但我们可以根据应用类型(系统应用/普通应用)来实现不同程度的自动操作,先从修正你现有代码的兼容性问题开始,再讲自动安装的具体方案。


第一步:先修正现有安装代码的兼容性问题

你的代码在Android 7.0+会触发FileUriExposedException,Android 8.0+还需要申请安装未知来源应用的权限,先把这些问题解决:

1. 配置权限和FileProvider

在AndroidManifest.xml中添加必要权限,并配置FileProvider(适配Android 7.0+的文件Uri规则):

<!-- 安装未知来源应用权限(Android 8.0+) -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!-- 读写存储权限(根据SDK版本适配) -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />

<application ...>
    <!-- 配置FileProvider -->
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>

在Resources/xml文件夹下创建file_paths.xml:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="." />
</paths>

2. 修正安装代码

更新你的ApkInstall方法,适配不同Android版本:

public void ApkInstall()
{
    try
    {
        var filename = "XYZ.apk";
        var path = "Install apk/";
        var apkFile = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Path.Combine(path, filename));
        
        System.Diagnostics.Debug.WriteLine($"APK路径:{apkFile.AbsolutePath}");

        Intent installIntent = new Intent(Intent.ActionInstallPackage);
        Android.Net.Uri apkUri;

        // 适配Android 7.0+的FileUri规则
        if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
        {
            apkUri = FileProvider.GetUriForFile(Android.App.Application.Context, 
                $"{Android.App.Application.Context.PackageName}.fileprovider", apkFile);
            installIntent.AddFlags(ActivityFlags.GrantReadUriPermission);
        }
        else
        {
            apkUri = Android.Net.Uri.FromFile(apkFile);
        }

        installIntent.SetDataAndType(apkUri, "application/vnd.android.package-archive");
        installIntent.SetFlags(ActivityFlags.NewTask);

        // Android 8.0+ 检查是否有安装未知应用的权限
        if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
        {
            if (!Android.App.Application.Context.PackageManager.CanRequestPackageInstalls())
            {
                // 跳转到权限设置页面让用户开启
                Intent permissionIntent = new Intent(Settings.ActionManageUnknownAppSources, 
                    Android.Net.Uri.Parse($"package:{Android.App.Application.Context.PackageName}"));
                ((Activity)Forms.Context).StartActivityForResult(permissionIntent, 1001);
                return;
            }
        }

        Forms.Context.StartActivity(installIntent);
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine($"安装出错:{ex.Message}");
    }
}

第二步:实现自动安装(分两种场景)

场景一:你的应用是系统应用/拥有系统签名

如果你的应用是预装系统应用,或者拥有系统签名,可以直接使用系统级权限实现完全自动安装,无需用户交互:

  1. 在AndroidManifest.xml添加系统权限:
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
  1. 使用PackageInstaller API实现自动安装:
public void AutoInstallSystemApp()
{
    var filename = "XYZ.apk";
    var path = "Install apk/";
    var apkFile = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Path.Combine(path, filename));

    PackageManager pm = Android.App.Application.Context.PackageManager;
    try
    {
        PackageInstaller installer = pm.PackageInstaller;
        PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.ModeFullInstall);
        int sessionId = installer.CreateSession(sessionParams);
        
        using (PackageInstaller.Session session = installer.OpenSession(sessionId))
        {
            // 将APK写入安装会话
            using (Stream inputStream = new FileStream(apkFile.AbsolutePath, FileMode.Open))
            {
                using (Stream outputStream = session.OpenWrite("apk", 0, -1))
                {
                    inputStream.CopyTo(outputStream);
                    session.Fsync(outputStream);
                }
            }
            
            // 提交安装请求,无需用户交互
            Intent intent = new Intent(Android.App.Application.Context, typeof(MainActivity));
            PendingIntent pendingIntent = PendingIntent.GetActivity(Android.App.Application.Context, 0, intent, PendingIntentFlags.UpdateCurrent);
            session.Commit(pendingIntent.IntentSender);
        }
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine($"自动安装出错:{ex.Message}");
    }
}

场景二:普通第三方应用(模拟用户点击)

对于普通第三方应用,Android不允许直接跳过用户交互,我们可以通过**辅助功能(AccessibilityService)**模拟点击安装按钮,实现“半自动”安装(需要用户先开启辅助功能权限):

  1. 创建辅助服务类
[Service(Label = "APK自动安装辅助服务", Permission = Manifest.Permission.BindAccessibilityService)]
[IntentFilter(new[] { Android.AccessibilityServices.AccessibilityService.ActionAccessibilityService })]
[MetaData(Android.AccessibilityServices.AccessibilityService.MetaDataName, Resource = "@xml/accessibility_service_config")]
public class AutoInstallAccessibilityService : AccessibilityService
{
    public override void OnAccessibilityEvent(AccessibilityEvent e)
    {
        if (e.EventType != EventTypes.WindowStateChanged) return;

        // 匹配系统安装界面的包名(不同厂商可能不同,比如小米是com.miui.securitycenter)
        var packageNames = new List<string> { "com.android.packageinstaller", "com.miui.securitycenter", "com.huawei.systemmanager" };
        if (!packageNames.Contains(e.PackageName.ToString())) return;

        var rootNode = RootInActiveWindow;
        if (rootNode == null) return;

        // 点击"安装"按钮
        ClickButtonByText(rootNode, "安装");
        // 安装完成后点击"完成"按钮
        ClickButtonByText(rootNode, "完成");
    }

    private void ClickButtonByText(AccessibilityNodeInfo root, string text)
    {
        List<AccessibilityNodeInfo> nodes = new List<AccessibilityNodeInfo>();
        FindNodesByText(root, text, nodes);
        
        foreach (var node in nodes)
        {
            if (node.IsEnabled)
            {
                node.PerformAction(global::Android.Views.Accessibility.ActionClick);
                break;
            }
        }
    }

    private void FindNodesByText(AccessibilityNodeInfo root, string text, List<AccessibilityNodeInfo> nodes)
    {
        if (root == null) return;
        if (text.Equals(root.Text)) nodes.Add(root);
        
        for (int i = 0; i < root.ChildCount; i++)
        {
            FindNodesByText(root.GetChild(i), text, nodes);
        }
    }

    public override void OnInterrupt()
    {
        // 服务被中断时的处理逻辑
    }
}
  1. 创建辅助服务配置文件
    在Resources/xml文件夹下创建accessibility_service_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canPerformGestures="true"
    android:description="@string/accessibility_service_description" />

在Resources/values/strings.xml添加服务描述:

<string name="accessibility_service_description">此服务用于自动完成APK安装操作,无需手动点击安装按钮</string>
  1. 引导用户开启辅助功能
    在启动安装前,先检查并引导用户开启辅助功能:
public void CheckAccessibilityPermission()
{
    var serviceName = $"{Android.App.Application.Context.PackageName}/{typeof(AutoInstallAccessibilityService).FullName}";
    AccessibilityManager am = (AccessibilityManager)Android.App.Application.Context.GetSystemService(Context.AccessibilityService);
    bool isEnabled = false;
    
    foreach (var service in am.GetEnabledAccessibilityServiceList(AccessibilityServiceInfo.FeedbackAllMask))
    {
        if (service.ResolveInfo.ServiceInfo.Name.Equals(serviceName))
        {
            isEnabled = true;
            break;
        }
    }

    if (!isEnabled)
    {
        // 跳转到辅助功能设置页面
        Intent intent = new Intent(Settings.ActionAccessibilitySettings);
        ((Activity)Forms.Context).StartActivity(intent);
    }
}

注意事项

  1. Android 11及以上系统对辅助功能的限制更严格,模拟点击可能会触发系统确认对话框。
  2. 不同厂商的系统安装界面包名和按钮文本不同,需要适配主流品牌(小米、华为、OPPO等)。
  3. 普通第三方应用无法完全绕过用户交互,这是Android的安全机制,防止恶意应用自动安装软件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:43:25