App Inventor 2 文件查找与文件管理教程

« 返回首页

概述

App Inventor 2内置的File组件可以读写文件,但无法列出目录。需要扩展实现文件浏览功能。

已有文档:file_operations.md 介绍了基本文件操作。本文聚焦文件查找和浏览。

内置File组件

读取文件

when 按钮_读取.Click() {
  文件管理器1.ReadFrom("/sdcard/MyApp/data.txt")
}
while 文件管理器1.GotText(文件名, 内容) {
  标签_内容.Text = 内容
}

保存文件

when 按钮_保存.Click() {
  文件管理器1.SaveFile(文本输入框_内容.Text, "/sdcard/MyApp/data.txt")
}

文件路径规则

路径 说明
/sdcard/ 外部存储根目录
/sdcard/Download/ 下载目录
/sdcard/DCIM/ 相册目录
/sdcard/Documents/ 文档目录
file:///android_asset/ App内部assets目录

Android 10+存储限制

Android 10引入了分区存储(Scoped Storage),App只能访问:

  • 自己的私有目录
  • 通过MediaStore访问的公共媒体
  • 用户通过系统文件选择器选择的文件

使用ListPicker选择文件

简单方案:预设文件列表

when Screen1.Initialize() {
  // 手动维护可用文件列表
  var 文件列表 = [ "data.txt", "config.json", "notes.md" ]
  列表选择器_文件.Elements = 文件列表
}
when 列表选择器_文件.AfterPicking(选中项) {
  文件管理器1.ReadFrom(join("/sdcard/MyApp/", 选中项))
}

使用ActivityStarter调用系统文件选择器

when 按钮_选择文件.Click() {
  Activity启动器1.Action = "android.intent.action.GET_CONTENT"
  Activity启动器1.DataUri = "file/*"
  Activity启动器1.DataType = "*/*"
  Activity启动器1.StartActivity()
}
when Activity启动器1.Result(结果, 数据) {
  if 结果 == "OK" {
    var 文件URI = Activity启动器1.ResultUri
    标签_文件路径.Text = 文件URI
    // 通过URI读取文件(可能需要扩展)
  }
}

使用FileTools扩展(推荐)

PuraVidaApps的FileTools扩展提供完整的文件管理功能:

列出目录文件

when 按钮_浏览.Click() {
  global 文件列表 = 文件管理器_Tools1.FileList("/sdcard/MyApp/")
  ListView_文件.Elements = 文件列表
}

when ListView_文件.AfterPicking() {
  global 文件路径 = join("/sdcard/MyApp/", ListView_文件.Selection)
  if (文件管理器_Tools1.IsDirectory(文件路径)) {
    // 是目录,进入
    global 新列表 = 文件管理器_Tools1.FileList(join(文件路径, "/"))
    ListView_文件.Elements = 新列表
    global 当前路径 = join(文件路径, "/")
  } else {
    // 是文件,读取
    文件管理器1.ReadFrom(文件路径)
  }
}

搜索文件

when 按钮_搜索.Click() {
  关键词 = 输入框_搜索.Text
  global 所有文件 = 文件管理器_Tools1.FileList("/sdcard/")
  global 匹配列表 = []
  
  for item in 所有文件 {
    if (containsText(item, 关键词)) {
      addItemsTo(匹配列表, item)
    }
  }
  
  ListView_搜索结果.Elements = 匹配列表
}

文件操作

// 复制文件
文件管理器_Tools1.CopyFile(源路径, 目标路径)
// 移动文件
文件管理器_Tools1.MoveFile(源路径, 目标路径)
// 删除文件
文件管理器_Tools1.Delete(文件路径)
// 重命名
文件管理器_Tools1.MoveFile(文件路径, 新名称)
// 获取文件大小
global 大小 = 文件管理器_Tools1.FileSize(文件路径)

简易文件浏览器实现

global 当前路径 = "/sdcard/"
global 路径历史 = []

when Screen1.Initialize() {
  导航到("/sdcard/")
}

procedure 导航到(路径) {
  global 当前路径 = 路径
  标签_路径.Text = 路径
  global 文件列表 = 文件管理器_Tools1.FileList(路径)
  
  global 显示列表 = []
  if (路径 != "/sdcard/") {
    addItemsTo(显示列表, "⬆️ ..(返回上级)")
  }
  
  for 名 in 文件列表 {
    global 完整路径 = join(路径, 名)
    if (文件管理器_Tools1.IsDirectory(完整路径)) {
      addItemsTo(显示列表, join("📁 ", 名))
    } else {
      addItemsTo(显示列表, join("📄 ", 名))
    }
  }
  
  ListView_文件.Elements = 显示列表
}

when ListView_文件.AfterPicking() {
  global 选中项 = ListView_文件.Selection
  if (starts_with(选中项, "⬆️")) {
    // 返回上级
    导航到(上级路径(当前路径))
  } else if (starts_with(选中项, "📁")) {
    // 进入目录
    目录名 = replaceAll(选中项, "📁 ", "")
    导航到(join(当前路径, 目录名, "/"))
  } else {
    // 选择文件
    文件名 = replaceAll(选中项, "📄 ", "")
    打开文件(join(当前路径, 文件名))
  }
}

权限

Android 6-9

when Screen1.Initialize() {
  Screen1.AskForPermission("android.permission.READ_EXTERNAL_STORAGE")
  Screen1.AskForPermission("android.permission.WRITE_EXTERNAL_STORAGE")
}

Android 10+

使用系统文件选择器或MediaStore API(需要扩展)。

常见问题

Q1: 文件路径错误?

  • 确认路径以 /sdcard/ 开头(或使用 文件管理器1.文档目录 获取正确路径)
  • Android 10+不要直接使用 /sdcard/,使用App私有目录
  • 使用 文件管理器1.文档目录 获取安全的路径

Q2: 无法读取某些目录?

  • Android系统限制了App访问其他App的私有目录
  • 使用系统文件选择器让用户选择文件

Q3: 没有FileTools扩展?

可以用ActivityStarter调用系统文件管理器作为替代方案。

总结

方案 功能 推荐度
File组件 读写指定文件 ⭐⭐⭐
ListPicker 预设文件列表 ⭐⭐
ActivityStarter 系统文件选择器 ⭐⭐⭐⭐
FileTools扩展 完整文件管理 ⭐⭐⭐⭐⭐
文档反馈