You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MAUI .NET Android端嵌入本地.mbtiles文件并实现可读取的方案(附读取代码示例请求)

MAUI .NET Android端嵌入本地.mbtiles文件并实现可读取的方案(附读取代码示例请求)

刚接触MAUI .NET安卓开发遇到这种文件路径问题太正常了,我之前也踩过类似的坑!核心问题在于:安卓的APK是压缩包结构,嵌入的资源没法直接像Windows那样通过文件名直接访问——SQLite需要的是一个真实的可写文件路径,而不是APK里的资源流。所以我们得先把嵌入的.mbtiles文件复制到应用的私有可访问目录,再从那里读取。

一、先正确配置文件的构建属性

  • 把你的FranceTETRoute.mbtiles文件放到项目的Resources/Raw目录下(如果没有这个目录就新建一个)
  • 在属性窗口里设置:
    • 构建操作:Embedded resource
    • 复制到输出目录:不复制(因为我们要用资源流读取,不需要复制到输出目录)

二、编写文件复制逻辑(应用启动时执行)

在应用启动的时候(比如App.xaml.csOnStart方法,或者MainPage的构造函数里),先检查目标目录是否已经存在这个文件,如果没有就从嵌入资源里复制过去:

using System.IO;
using System.Reflection;

// 复制嵌入的mbtiles文件到安卓可写目录
private async Task CopyMbtilesToLocalAsync()
{
    // 目标文件路径:安卓应用的私有数据目录
    var targetFilePath = Path.Combine(FileSystem.AppDataDirectory, "FranceTETRoute.mbtiles");

    // 如果文件已经存在,就不用重复复制了
    if (File.Exists(targetFilePath))
        return;

    // 获取嵌入资源的流:注意这里的资源名要和你的项目命名空间+文件路径对应
    // 比如你的项目命名空间是MyMauiMapApp,文件在Resources/Raw下,资源名就是MyMauiMapApp.Resources.Raw.FranceTETRoute.mbtiles
    var assembly = Assembly.GetExecutingAssembly();
    var resourceName = "YourProjectNamespace.Resources.Raw.FranceTETRoute.mbtiles";

    using var resourceStream = assembly.GetManifestResourceStream(resourceName);
    if (resourceStream == null)
        throw new FileNotFoundException("找不到嵌入的mbtiles资源,请检查资源名是否正确");

    // 复制流到目标文件
    using var fileStream = new FileStream(targetFilePath, FileMode.CreateNew);
    await resourceStream.CopyToAsync(fileStream);
}

三、读取mbtiles文件的代码示例

复制完成后,就可以用这个目标路径来创建SQLite连接了,和你在Windows上的逻辑类似,只是路径换成了我们复制后的私有目录路径:

using SQLite;

// 读取mbtiles文件的示例方法
private async Task ReadMbtilesDataAsync()
{
    var dbPath = Path.Combine(FileSystem.AppDataDirectory, "FranceTETRoute.mbtiles");
    
    // 确认文件存在后创建连接
    if (!File.Exists(dbPath))
        await CopyMbtilesToLocalAsync();

    using var conn = new SQLiteConnection(dbPath);
    // 这里就可以执行你的SQLite操作了,比如查询元数据
    var metadata = conn.Query<Metadata>("SELECT * FROM metadata");
    foreach (var item in metadata)
    {
        Console.WriteLine($"{item.Name}: {item.Value}");
    }
}

// 对应的Metadata实体类,根据mbtiles的结构定义
public class Metadata
{
    public string Name { get; set; }
    public string Value { get; set; }
}

几个关键注意点

  • 资源名一定要对应正确!如果拿不准,可以用Assembly.GetExecutingAssembly().GetManifestResourceNames()打印所有嵌入资源的名字,找到你的mbtiles文件对应的那个。
  • 应用的FileSystem.AppDataDirectory是安卓的私有目录,只有当前应用能访问,不用担心权限问题,也不需要申请额外的存储权限。
  • 不要用“Maui Asset”作为构建操作,因为Asset目录的文件也是在APK里,没法直接被SQLite以文件路径的方式读取,还是得复制出来。

内容来源于stack exchange

火山引擎 最新活动