2025-10-11 18:25:59 +08:00

314 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Android.Content;
using Android.Content.PM;
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.Text.Json;
namespace XiaoZhiSharp_MauiApp.Platforms.Android.McpTools
{
[McpServerToolType]
public sealed class AndroidApp_Tool
{
[McpServerTool, Description("打开指定的Android应用。参数appName - 应用名称或包名")]
public static string OpenApp(string appName)
{
try
{
var context = Platform.CurrentActivity ?? global::Android.App.Application.Context;
var packageManager = context.PackageManager;
// 首先尝试通过包名打开
if (TryOpenAppByPackageName(context, packageManager, appName))
{
return $"成功打开应用: {appName}";
}
// 如果包名方式失败,尝试通过应用名称查找
var packageName = FindPackageByAppName(packageManager, appName);
if (!string.IsNullOrEmpty(packageName))
{
if (TryOpenAppByPackageName(context, packageManager, packageName))
{
return $"成功打开应用: {appName} (包名: {packageName})";
}
}
return $"未找到应用: {appName}";
}
catch (Exception ex)
{
return $"打开应用失败: {ex.Message}";
}
}
[McpServerTool, Description("列出所有已安装的应用")]
public static string ListInstalledApps()
{
try
{
var context = Platform.CurrentActivity ?? global::Android.App.Application.Context;
var packageManager = context.PackageManager;
var packages = packageManager.GetInstalledApplications(PackageInfoFlags.MatchAll);
var appList = new List<object>();
foreach (var package in packages)
{
// 只列出有启动器图标的应用(用户应用)
var launchIntent = packageManager.GetLaunchIntentForPackage(package.PackageName);
if (launchIntent != null)
{
var appName = packageManager.GetApplicationLabel(package)?.ToString() ?? package.PackageName;
appList.Add(new
{
Name = appName,
PackageName = package.PackageName
});
}
}
// 按应用名称排序
appList = appList.OrderBy(app => ((dynamic)app).Name).ToList();
return JsonSerializer.Serialize(new
{
Success = true,
Count = appList.Count,
Apps = appList
}, new JsonSerializerOptions { WriteIndented = true });
}
catch (Exception ex)
{
return JsonSerializer.Serialize(new
{
Success = false,
Error = ex.Message
});
}
}
[McpServerTool, Description("搜索应用。参数keyword - 搜索关键词")]
public static string SearchApp(string keyword)
{
try
{
var context = Platform.CurrentActivity ?? global::Android.App.Application.Context;
var packageManager = context.PackageManager;
var packages = packageManager.GetInstalledApplications(PackageInfoFlags.MatchAll);
var searchResults = new List<object>();
keyword = keyword.ToLower();
foreach (var package in packages)
{
var launchIntent = packageManager.GetLaunchIntentForPackage(package.PackageName);
if (launchIntent != null)
{
var appName = packageManager.GetApplicationLabel(package)?.ToString() ?? package.PackageName;
// 搜索应用名称或包名
if (appName.ToLower().Contains(keyword) || package.PackageName.ToLower().Contains(keyword))
{
searchResults.Add(new
{
Name = appName,
PackageName = package.PackageName
});
}
}
}
return JsonSerializer.Serialize(new
{
Success = true,
Keyword = keyword,
Count = searchResults.Count,
Results = searchResults
}, new JsonSerializerOptions { WriteIndented = true });
}
catch (Exception ex)
{
return JsonSerializer.Serialize(new
{
Success = false,
Error = ex.Message
});
}
}
[McpServerTool, Description("打开系统设置")]
public static string OpenSettings()
{
try
{
var context = Platform.CurrentActivity ?? global::Android.App.Application.Context;
var intent = new Intent(global::Android.Provider.Settings.ActionSettings);
intent.AddFlags(ActivityFlags.NewTask);
context.StartActivity(intent);
return "成功打开系统设置";
}
catch (Exception ex)
{
return $"打开设置失败: {ex.Message}";
}
}
[McpServerTool, Description("打开指定的系统设置页面。参数settingType - 设置类型(wifi/bluetooth/location/app_settings/notification/display/sound/battery)")]
public static string OpenSpecificSettings(string settingType)
{
try
{
var context = Platform.CurrentActivity ?? global::Android.App.Application.Context;
Intent intent;
switch (settingType.ToLower())
{
case "wifi":
intent = new Intent(global::Android.Provider.Settings.ActionWifiSettings);
break;
case "bluetooth":
intent = new Intent(global::Android.Provider.Settings.ActionBluetoothSettings);
break;
case "location":
intent = new Intent(global::Android.Provider.Settings.ActionLocationSourceSettings);
break;
case "app_settings":
intent = new Intent(global::Android.Provider.Settings.ActionApplicationDetailsSettings);
intent.SetData(global::Android.Net.Uri.Parse($"package:{context.PackageName}"));
break;
case "notification":
intent = new Intent(global::Android.Provider.Settings.ActionNotificationListenerSettings);
break;
case "display":
intent = new Intent(global::Android.Provider.Settings.ActionDisplaySettings);
break;
case "sound":
intent = new Intent(global::Android.Provider.Settings.ActionSoundSettings);
break;
case "battery":
intent = new Intent(global::Android.Provider.Settings.ActionBatterySaverSettings);
break;
default:
return $"不支持的设置类型: {settingType}";
}
intent.AddFlags(ActivityFlags.NewTask);
context.StartActivity(intent);
return $"成功打开{settingType}设置";
}
catch (Exception ex)
{
return $"打开设置失败: {ex.Message}";
}
}
private static bool TryOpenAppByPackageName(Context context, PackageManager packageManager, string packageName)
{
try
{
var launchIntent = packageManager.GetLaunchIntentForPackage(packageName);
if (launchIntent != null)
{
launchIntent.AddFlags(ActivityFlags.NewTask);
context.StartActivity(launchIntent);
return true;
}
}
catch (Exception)
{
// 忽略异常返回false
}
return false;
}
private static string? FindPackageByAppName(PackageManager packageManager, string appName)
{
try
{
var packages = packageManager.GetInstalledApplications(PackageInfoFlags.MatchAll);
appName = appName.ToLower();
// 首先尝试精确匹配
foreach (var package in packages)
{
var launchIntent = packageManager.GetLaunchIntentForPackage(package.PackageName);
if (launchIntent != null)
{
var installedAppName = packageManager.GetApplicationLabel(package)?.ToString()?.ToLower();
if (installedAppName == appName)
{
return package.PackageName;
}
}
}
// 如果精确匹配失败,尝试模糊匹配
foreach (var package in packages)
{
var launchIntent = packageManager.GetLaunchIntentForPackage(package.PackageName);
if (launchIntent != null)
{
var installedAppName = packageManager.GetApplicationLabel(package)?.ToString()?.ToLower();
if (installedAppName?.Contains(appName) == true)
{
return package.PackageName;
}
}
}
// 特殊应用名称映射
var specialApps = new Dictionary<string, string[]>
{
{ "微信", new[] { "com.tencent.mm", "wechat" } },
{ "支付宝", new[] { "com.eg.android.AlipayGphone", "alipay" } },
{ "qq", new[] { "com.tencent.mobileqq", "com.tencent.qq" } },
{ "淘宝", new[] { "com.taobao.taobao", "taobao" } },
{ "抖音", new[] { "com.ss.android.ugc.aweme", "douyin", "tiktok" } },
{ "百度", new[] { "com.baidu.searchbox", "baidu" } },
{ "高德地图", new[] { "com.autonavi.minimap", "amap" } },
{ "美团", new[] { "com.sankuai.meituan", "meituan" } },
{ "京东", new[] { "com.jingdong.app.mall", "jd" } },
{ "网易云音乐", new[] { "com.netease.cloudmusic", "cloudmusic" } },
{ "bilibili", new[] { "tv.danmaku.bili", "com.bilibili.app.in" } },
{ "知乎", new[] { "com.zhihu.android", "zhihu" } },
{ "小红书", new[] { "com.xingin.xhs", "xiaohongshu" } },
{ "携程", new[] { "ctrip.android.view", "ctrip" } },
{ "饿了么", new[] { "me.ele", "eleme" } }
};
// 检查特殊应用映射
foreach (var kvp in specialApps)
{
if (appName.Contains(kvp.Key) || kvp.Value.Any(v => appName.Contains(v)))
{
foreach (var possiblePackage in kvp.Value)
{
if (IsPackageInstalled(packageManager, possiblePackage))
{
return possiblePackage;
}
}
}
}
}
catch (Exception)
{
// 忽略异常
}
return null;
}
private static bool IsPackageInstalled(PackageManager packageManager, string packageName)
{
try
{
packageManager.GetPackageInfo(packageName, PackageInfoFlags.MatchAll);
return true;
}
catch (PackageManager.NameNotFoundException)
{
return false;
}
}
}
}