Xamarin开发Wear OS应用无法读取Galaxy Wearable添加的音频文件
我用Xamarin开发Wear OS手表应用,需要获取通过Galaxy Wearable手机App添加的音频曲目。通过ADB和myWear文件管理器能看到手表的/sdcard/music/GalaxyWearable目录下有文件,但调用Directory.GetFiles("/sdcard/music/GalaxyWearable");返回0个文件。已经在AndroidManifest.xml添加了以下权限但无效:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MANAGE_DOCUMENT" />
原因及解决办法
1. Android 10+ 分区存储限制
Android 10及以上引入了分区存储机制,即使声明了READ_EXTERNAL_STORAGE,普通文件API也无法直接访问其他App创建的私有关联目录。Galaxy Wearable同步的音频文件属于这类目录,需改用MediaStore API或**存储访问框架(SAF)**读取。
2. 权限未动态申请
Android 6.0+要求危险权限必须动态申请,仅在Manifest中声明无效。READ_EXTERNAL_STORAGE和MANAGE_EXTERNAL_STORAGE都需要动态请求,其中MANAGE_EXTERNAL_STORAGE是特殊权限,需引导用户到系统设置手动开启。
具体操作步骤
(1)动态申请基础存储权限
在Xamarin中用Permissions.RequestAsync请求读取权限:
var status = await Permissions.RequestAsync<Permissions.StorageRead>(); if (status != PermissionStatus.Granted) { // 处理权限拒绝逻辑,比如提示用户开启权限 return; }
(2)用MediaStore查询Galaxy Wearable下的音频文件
针对分区存储限制,通过MediaStore筛选目标目录的音频:
var uri = MediaStore.Audio.Media.ExternalContentUri; string[] projection = { MediaStore.Audio.Media.Data }; string selection = $"{MediaStore.Audio.Media.Data} LIKE ?"; string[] selectionArgs = new[] { "%/sdcard/music/GalaxyWearable/%" }; using (var cursor = ContentResolver.Query(uri, projection, selection, selectionArgs, null)) { if (cursor != null && cursor.MoveToFirst()) { do { string filePath = cursor.GetString(cursor.GetColumnIndexOrThrow(MediaStore.Audio.Media.Data)); // 处理获取到的文件路径 } while (cursor.MoveToNext()); } }
(3)申请MANAGE_EXTERNAL_STORAGE权限(仅Android 11+)
如果必须使用传统文件API访问,需申请该特殊权限(注意:Google Play对该权限的使用有严格审核要求,非必要不建议用):
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.R) { if (!Environment.IsExternalStorageManager) { var intent = new Intent(Android.Provider.Settings.ActionManageAppAllFilesAccessPermission); intent.SetData(Android.Net.Uri.Parse($"package:{PackageName}")); StartActivity(intent); } }
(4)避免硬编码路径,用标准API获取目录
改用Android系统提供的API获取音乐目录,避免路径错误:
var musicDir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMusic); var galaxyWearableDir = new Java.IO.File(musicDir, "GalaxyWearable"); if (galaxyWearableDir.Exists()) { var files = galaxyWearableDir.ListFiles(); // 处理文件列表 }
内容的提问来源于stack exchange,提问作者LibUsbDotNet Support

