Android学习笔记——文件路径(/mnt/sdcard/...)、Uri(content://media/external/...)学习

本文详细介绍了Android中URI的使用方式及其在多媒体文件管理中的应用,包括如何通过URI获取文件路径和由路径得到URI的方法,以及Android内部如何管理多媒体文件的信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


  一、URI 

  通用资源标志符(Universal Resource Identifier, 简称"URI")。

  Uri代表要操作的数据,Android上可用的每种资源 - 图像、视频片段等都可以用Uri来表示。

  URI一般由三部分组成:

    访问资源的命名机制。 

    存放资源的主机名。 

    资源自身的名称,由路径表示。 

  Android的Uri由以下三部分组成: "content://"、数据的路径、标示ID(可选)

  举些例子,如: 

    所有联系人的Uri: content://contacts/people

    某个联系人的Uri: content://contacts/people/5

    所有图片Uri: content://media/external

    某个图片的Uri:content://media/external/images/media/4

 

  二、内部保存

  首先我们来看一下android是如何管理多媒体文件(音频、视频、图片)的信息。通过DDMS,我们在/data/data/com.android.providers.media下找到数据库文件

  

  打开external.db文件进一步查看:在media表格下,可以看到文件路径(_data)和Uri的标示ID(_id)的对应关系。

  

  三、相互转换

   1.从URI获得文件路径

   

复制代码
 1     string  myImageUrl = "content://media/external/images/media/***";
 2     Uri uri = Uri.parse(myImageUrl);
 3     
 4 
 5     String[] proj = { MediaStore.Images.Media.DATA };   
 6     Cursor actualimagecursor = this.ctx.managedQuery(uri,proj,null,null,null);  
 7     int actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);   
 8     actualimagecursor.moveToFirst();   
 9     
10 
11     String img_path = actualimagecursor.getString(actual_image_column_index);  
12     File file = new File(img_path);
13     Uri fileUri = Uri.fromFile(file);
复制代码

 

 

  2.由文件路径得到URI

  

复制代码
 1             Uri mUri = Uri.parse("content://media/external/images/media"); 
 2             Uri mImageUri = null;
 3 
 4             Cursor cursor = managedQuery(
 5                     MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null,
 6                     null, MediaStore.Images.Media.DEFAULT_SORT_ORDER);
 7             cursor.moveToFirst();
 8 
 9             while (!cursor.isAfterLast()) {
10                 String data = cursor.getString(cursor
11                         .getColumnIndex(MediaStore.MediaColumns.DATA));
12                 if (picPath.equals(data)) {
13                     int ringtoneID = cursor.getInt(cursor
14                             .getColumnIndex(MediaStore.MediaColumns._ID));
15                     mImageUri = Uri.withAppendedPath(mUri, ""
16                             + ringtoneID);
17                     break;
18                 }
19                 cursor.moveToNext();
20             }
复制代码

 

<think>我们正在解决用户的问题:用户尝试卸载挂载点时出现错误提示 `sudo umount /mnt/ios: no mount point specified error`。实际上,这个错误信息可能是用户输入命令时的一个笔误,因为错误信息中提到了`/mnt/ios`,而用户之前的问题中挂载点是`/mnt/iso`(注意iso和ios的差别)。但根据用户当前的问题,他输入的命令是`sudo umount /mnt/ios`,而系统提示“no mount point specified”,这通常是因为命令格式不正确。 让我们分析一下: 用户输入的命令是:`sudo umount /mnt/ios: no mount point specified error` 实际上,这个输入看起来像是在描述错误,而不是实际输入的命令。因为命令中包含了错误信息。所以我们需要重新理解用户的问题。 用户说:“我想解决卸载挂载点时出现的错误提示 请问sudo umount /mnt/ios: no mount point specified error” 这可能是用户执行了类似`sudo umount /mnt/ios`的命令,然后系统返回了错误信息,但是错误信息可能是“umount: /mnt/ios: no mount point specified”或者类似内容。然而,标准的umount命令的错误信息中,如果挂载点不存在,通常会提示“umount: /mnt/ios: not mounted”或者“umount: /mnt/ios: no such file or directory”。而“no mount point specified”通常是因为没有指定挂载点,即命令中缺少了挂载点参数。 实际上,umount命令的语法是: umount <设备或挂载点> 如果执行`sudo umount`后面没有跟任何参数,就会提示“no mount point specified”。 因此,用户可能是在输入命令时,在`/mnt/ios`后面多输入了一个冒号(:),或者命令格式写错了。 但是用户给出的错误信息是:`sudo umount /mnt/ios: no mount point specified error`,这看起来像是用户将整个错误信息作为命令输入了?这显然是不对的。 所以,我们推测用户实际执行的是: sudo umount /mnt/ios 然后系统返回的错误可能是其他内容,但用户描述为“no mount point specified error”。 然而,根据经验,umount命令常见的错误有: 1. 挂载点不存在(即目录不存在) -> 错误信息:umount: /mnt/ios: no such file or directory 2. 挂载点存在但没有挂载文件系统 -> 错误信息:umount: /mnt/ios: not mounted 3. 挂载点正忙(有进程在使用) -> 错误信息:umount: /mnt/ios: target is busy 所以,我们需要用户确认错误信息的具体内容。但根据用户描述,他认为是“no mount point specified”,这通常是因为命令中忘记写挂载点参数了。 因此,我们怀疑用户输入命令时可能误将冒号作为命令的一部分了。例如,用户可能输入了: sudo umount /mnt/ios: # 注意后面的冒号 这样,系统会认为冒号是参数的一部分,即挂载点是`/mnt/ios:`,而这个目录通常不存在,所以会报错。 解决方案: 1. 检查命令中是否有多余的字符(如冒号)。 2. 确保挂载点路径正确。 另外,用户之前的问题中挂载点是`/mnt/iso`,而这里写的是`/mnt/ios`,可能是笔误。 因此,我们分步骤解决: 步骤1:确认挂载点路径 - 用户之前挂载的是`/mnt/iso`,现在要卸载的是`/mnt/ios`,这两个路径不同。所以需要确认用户是否确实挂载到了`/mnt/ios`,还是说应该是`/mnt/iso`? 步骤2:检查挂载点是否存在 - 使用`ls -ld /mnt/ios`(或`/mnt/iso`)查看目录是否存在。 步骤3:检查该挂载点是否已挂载 - 使用`mount | grep '/mnt/ios'` 或 `mount | grep '/mnt/iso'` 来查看。 步骤4:如果挂载点确实存在且已挂载,则正常卸载 - `sudo umount /mnt/ios` 或 `sudo umount /mnt/iso` 步骤5:如果遇到“target is busy”,则需要按照之前引用[5]的方法处理(使用fuser或lsof找出占用进程并结束,或者退出终端重新登录后再卸载) 但是,用户现在报告的错误是“no mount point specified”,所以我们重点检查命令格式。 因此,我们建议用户重新输入命令,确保没有多余字符,并且挂载点路径正确。 具体步骤: 1. **检查命令格式**: 确保命令为:`sudo umount /mnt/ios` (注意:没有冒号,没有多余字符) 2. **如果挂载点路径是`/mnt/iso`,则应该使用**: `sudo umount /mnt/iso` 3. **如果挂载点不存在**(比如目录被删除): 首先,使用`mount`命令查看当前挂载的所有文件系统,找到对应的挂载点(可能是其他路径)或者设备(比如`/dev/loop0`),然后通过设备卸载: ```bash sudo umount /dev/loop0 # 将loop0替换为实际设备 ``` 4. **如果挂载点目录已经被删除**,但设备仍然挂载着,这时卸载方法: ```bash # 首先找到挂载的设备 mount | grep '/mnt/ios' # 如果找不到,尝试其他相关关键字 # 如果找到,例如:/dev/loop0 on /mnt/ios type vfat (rw,...) sudo umount /dev/loop0 ``` 5. **如果上述方法都不行**,可以尝试使用懒卸载(lazy unmount),强制卸载: ```bash sudo umount -l /mnt/ios ``` 注意:这可能会影响正在使用该文件系统的进程。 6. **如果目录不存在,且无法确定设备**,可以查看所有挂载的loop设备: ```bash sudo losetup -a ``` 然后卸载对应的loop设备。 7. **如果是因为挂载点目录不存在而导致无法卸载**,可以重新创建目录,然后尝试再次挂载(这样就能覆盖原来的挂载),然后再卸载: ```bash sudo mkdir /mnt/ios sudo mount -o loop efi.img /mnt/ios # 这里假设使用efi.img,仅用于覆盖挂载 sudo umount /mnt/ios ``` 但是,这种方法可能不总是有效,因为原来的挂载可能已经不可访问。所以更推荐使用懒卸载或者通过设备卸载。 根据引用[5],如果遇到设备忙(target is busy)的情况,可以使用`fuser`或`lsof`来查找占用进程,然后结束进程或者退出终端重新登录。 因此,我们针对用户当前的问题,给出以下解决方案: 解决方案: 1. **检查命令输入**: 确保命令正确:`sudo umount /mnt/ios` (注意不要有多余的冒号或其他字符) 2. **确认挂载点路径**: 使用`ls -d /mnt/ios`检查目录是否存在。如果不存在,则使用`mount`命令查看当前挂载列表,找到正确的挂载点。 3. **使用设备卸载**: 如果挂载点目录不存在,但设备仍然挂载,可以通过设备卸载: ```bash # 查找挂载的设备 mount | grep '/mnt/ios' # 如果没有输出,尝试查找其他可能的挂载点(比如/mnt/iso) mount | grep 'efi.img' # 假设挂载的是efi.img文件 # 找到设备后,使用设备路径卸载 sudo umount /dev/loop0 # 替换为实际设备 ``` 4. **懒卸载**: ```bash sudo umount -l /mnt/ios ``` 5. **处理挂载点不存在的情况**: 如果挂载点目录被删除,可以尝试重新创建目录,然后挂载一个无关文件系统(如tmpfs)到该目录,再卸载: ```bash sudo mkdir -p /mnt/ios sudo mount -t tmpfs tmpfs /mnt/ios # 挂载一个临时文件系统 sudo umount /mnt/ios ``` 这样就能解除原先的挂载(因为挂载被覆盖了)。 6. **重启系统**:如果以上方法都不行,重启系统会解除所有挂载。 由于用户描述的错误信息是“no mount point specified”,我们首先怀疑命令格式问题。因此,重点检查命令中是否有多余字符,并确保挂载点参数正确。 根据引用[2],sudoers配置可能会影响命令执行,但这里umount命令不需要特殊sudoers配置,所以可能性低。 最后,我们给出一个标准的解决流程: 步骤: 1. 检查输入命令:`sudo umount /mnt/ios` (确保没有多余字符) 2. 如果提示“umount: /mnt/ios: not mounted”或“umount: /mnt/ios: no such file or directory”,则说明该挂载点不存在或未挂载。此时,使用`mount`命令查看所有挂载,找到正确的挂载点。 3. 如果挂载点目录不存在,则重新创建目录(`sudo mkdir /mnt/ios`)然后尝试再次卸载?注意:创建目录并不能让已经挂载的目录回来,所以这一步可能没用。所以更推荐通过设备卸载。 4. 使用懒卸载:`sudo umount -l /mnt/ios` 5. 如果仍然不行,重启系统。 注意:用户之前的问题中,挂载的是`efi.img`到`/mnt/iso`,所以这里用户可能是想卸载`/mnt/iso`,但误写成了`/mnt/ios`。因此,建议用户尝试: `sudo umount /mnt/iso` 综上所述,我们按照以下步骤回答用户:</think>### 解决 `sudo umount /mnt/ios: no mount point specified` 错误 这个错误通常由以下原因引起,请按顺序排查: --- #### 1. **挂载点路径错误或不存在**(最常见原因) ```bash # 检查挂载点目录是否存在 ls -ld /mnt/ios # 正确做法:创建挂载点目录 sudo mkdir -p /mnt/ios # -p 确保父目录存在 ``` --- #### 2. **命令语法错误**(多出冒号) 您的命令中包含多余的冒号 `:`: ```diff - sudo umount /mnt/ios: # 错误语法(末尾冒号) + sudo umount /mnt/ios # 正确语法 ``` 挂载点路径 **不能包含冒号**,系统会将 `/mnt/ios:` 视为无效路径。 --- #### 3. **确认实际挂载点** ```bash # 查看所有已挂载点 mount | grep ios # 若未返回结果,说明未挂载 sudo umount -l /mnt/ios 2>/dev/null # 安全清理残留挂载 ``` --- #### 4. **挂载点被占用**(参考引用[5]) ```bash # 检查占用进程 sudo lsof +D /mnt/ios # 列出使用目录的进程 sudo fuser -vm /mnt/ios # 查看文件使用者 # 若显示 "no mount point specified" 仍出现 sudo umount -f /mnt/ios # 强制卸载(慎用) ``` --- #### 5. **文件系统未正确卸载** 若之前强制关机或崩溃: ```bash # 修复文件系统 sudo fsck /dev/sdXN # 替换为实际设备如 /dev/sda1 # 清理挂载缓存 sudo systemctl daemon-reload ``` --- ### 关键说明 1. **正确命令格式**: ```bash sudo umount <挂载点路径> # 路径必须存在且无特殊符号 ``` 2. **挂载点要求**(引用[4]): - 必须是**已存在的空目录** - 路径不能包含 `:` 等特殊字符 - 父目录需有执行权限 (`chmod +x /mnt`) 3. **备用解决方案**: ```bash # 通过设备路径卸载(需先确认设备名) sudo umount /dev/sdXN # 如 /dev/sda1 # 懒卸载(断开文件系统,等程序退出后自动卸载) sudo umount -l /mnt/ios ``` > **操作示例**: > ```bash > # 创建挂载点 > sudo mkdir -p /mnt/ios > > # 挂载设备(示例) > sudo mount /dev/sdb1 /mnt/ios > > # 正确卸载 > sudo umount /mnt/ios # 不是 umount /mnt/ios: > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值