Android如何获得指定文件的Uri

许多情况下,我们要获得指定文件的Uri,费话不多说直接上代码:

通过已知路径来获得audio文件的uri

	
	/**
	 * 查找在于SDcard中的Audio文件对应于MediaStore  的uri
	 * @param file 音频文件
	 * @return
	 */
	public Uri queryUriforAudio(File file)

	{

		final String where = MediaStore.Audio.Media.DATA + "='"+file.getAbsolutePath()+"'";

		Cursor cursor=query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, where, null, null);

		if (cursor == null) {

			return null;

		}

		int id = -1;

		if (cursor != null) {

			cursor.moveToFirst();

			if (!cursor.isAfterLast()) {

				id = cursor.getInt(0);

			}

			cursor.close();

		}

		if(id==-1)

		{

			return null;

		}

		return Uri.withAppendedPath(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, String.valueOf(id));

	}

关于Video的可能有些不同,见代码

	/**
	 * 查找视频文件对应于MediaStore的Uri
	 * @param file 视频文件 
	 * @return
	 */
	
	private Uri queryUriForVideo(File file){
				int id = getId(file);			

				if(id==-1)

				{

					return null;

				}

				return Uri.withAppendedPath(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, String.valueOf(id));
	}

/**
 * 获得 指定视频文件F在MediaStore中对应的ID
 * @param f  视频文件
 * @return  对应ID
 */
	
	private int getId(File f){
		int id = -1;
		// MediaStore.Video.Media.DATA:视频文件路径;
		// MediaStore.Video.Media.DISPLAY_NAME : 视频文件名,如 testVideo.mp4
		// MediaStore.Video.Media.TITLE: 视频标题 : testVideo
		String[] mediaColumns = { MediaStore.Video.Media._ID,
				MediaStore.Video.Media.DATA, MediaStore.Video.Media.TITLE,
				MediaStore.Video.Media.MIME_TYPE,
				MediaStore.Video.Media.DISPLAY_NAME };
		
		final String where = MediaStore.Video.Media.DATA + "="+"?";
		
	 Cursor	cursor = managedQuery(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
				mediaColumns, where, new String[]{f.getAbsolutePath()}, null);
		if(cursor==null){
			Toast.makeText(this, "没有找到可播放视频文件", 1).show();
			return -1;
		}
		
		if (cursor.moveToFirst()) {
			do {
				id = cursor.getInt(cursor
						.getColumnIndex(MediaStore.Video.Media._ID));
		
				//sysVideoList.add(info);
			} while (cursor.moveToNext());
		}
		return id;
		
	}






<think>好的,用户的问题是想要在Android 34中解决获取文件URI的问题。首先,我需要回忆一下Android版本中关于文件URI的变化。根据用户提供的引用,Android 7.0(API 24)开始禁止使用file:// URI,需要使用content:// URI,特别是通过FileProvider来生成。现在用户提到的是Android 34,也就是Android 14,所以同样的策略应该适用,但可能需要检查是否有新的变化。 首先,用户之前的错误是关于PdfiumCore的UnsatisfiedLinkError,这可能与本地库加载有关,但当前问题转向了文件URI的处理。需要明确用户当前的问题是否与之前的问题相关,但根据用户现在的提问,重点在Android 14获取文件URI的正确方法。 根据引用[2],使用FileProvider生成content URI是正确的做法。可能需要详细说明如何在AndroidManifest中配置FileProvider,包括定义provider和指定文件路径。此外,用户提到需要访问根目录的文件,这可能涉及到使用Storage Access Framework或者请求适当的权限,比如MANAGE_EXTERNAL_STORAGE,但需要注意Google Play对此权限的限制。 另外,用户引用中提到在WebView中处理文件选择器时可能遇到的问题,如URI没有扩展名,这可能涉及到使用ContentResolver来打开输入流并处理文件内容,确保应用能够正确读取内容URI对应的文件。同时,要注意Android 11(API 30)引入的Scoped Storage,这进一步限制了应用对外部存储的访问,必须使用SAF或MediaStore API。 可能用户的应用需要访问特定目录,比如下载目录或者自定义目录,这时候需要正确配置FileProvider的路径,并确保生成的URI正确。此外,处理Intent的时候,需要设置正确的权限标志,如FLAG_GRANT_READ_URI_PERMISSION,以便其他应用(如文件选择器)能够临时访问该URI。 还需要考虑Android 14是否有新的权限要求或API变动,比如可能需要动态请求权限,或者使用特定的API来访问公共目录。同时,要提醒用户测试在不同Android版本上的兼容性,确保解决方案在较旧版本上也能正常工作。 总结步骤应该是:配置FileProvider,生成content URI,处理权限,使用ContentResolver读取文件,以及处理可能的路径转换问题。同时,要提到替代方案如Storage Access Framework,并警告关于MANAGE_EXTERNAL_STORAGE的使用限制。</think>针对Android 14(API 34)中安全获取文件URI的需求,以下是基于Android最新安全规范的解决方案: ### 一、FileProvider核心配置 1. **AndroidManifest声明** 在`<application>`标签内添加FileProvider定义: ```xml <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> ``` 2. **路径映射文件** 创建`res/xml/file_paths.xml`定义可访问路径: ```xml <paths> <!-- 访问应用私有目录 --> <files-path name="private_files" path="."/> <!-- 访问公共下载目录 --> <external-path name="downloads" path="Download"/> <!-- 自定义根目录访问(需动态权限) --> <root-path name="system_root" path="."/> </paths> ``` 注意:`<root-path>`需要`MANAGE_EXTERNAL_STORAGE`权限[^1] ### 二、URI生成与使用 1. **安全URI生成** 替换传统的`Uri.fromFile()`方法: ```java File file = new File("/sdcard/Download/report.pdf"); Uri uri = FileProvider.getUriForFile( context, context.getPackageName() + ".fileprovider", file ); ``` 2. **跨进程权限授予** 通过Intent传递URI时添加临时权限: ```java Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(uri, "application/pdf"); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); ``` ### 三、Android 14新增适配 1. **分区存储强化** 即使设置`requestLegacyExternalStorage=true`,在Android 14上也必须使用以下方法访问公共目录: ```java ContentResolver resolver = context.getContentResolver(); Uri contentUri = MediaStore.Downloads.getContentUri("external"); Cursor cursor = resolver.query(contentUri, new String[]{MediaStore.Downloads._ID}, MediaStore.Downloads.TITLE + "=?", new String[]{"report.pdf"}, null); ``` 2. **路径回退机制** 当需要绝对路径时(如调用NDK库): ```java String path = null; if ("file".equals(uri.getScheme())) { path = uri.getPath(); } else { try (InputStream is = resolver.openInputStream(uri)) { File cacheFile = new File(context.getCacheDir(), "temp.pdf"); // 实现流到文件的拷贝逻辑... path = cacheFile.getAbsolutePath(); } } ``` ### 四、特殊权限申请 对根目录访问需要向用户申请特殊权限: ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); intent.setData(Uri.parse("package:" + context.getPackageName())); startActivity(intent); } ``` 注意:使用该权限会导致Google Play审核更严格[^1] ### 五、调试验证方法 ```java // 检查URI权限 int modeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; context.checkUriPermission(uri, Process.myPid(), Process.myUid(), modeFlags); // 获取真实路径调试 String realPath = getRealPathFromURI(context, uri); Log.d("URI Debug", "Mapped path: " + realPath); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值