要使用Intent选择音频文件,我正在使用此功能:-
fun selectAudioFromStorage() {
val pictureActionIntent = Intent(Intent.ACTION_GET_CONTENT, null)
pictureActionIntent.type = "audio/*"
pictureActionIntent.putExtra("return-data", true)
startActivityForResult(pictureActionIntent, ResultConstants.RC_SELECT_AUDIO)
}
片段类的onActivityResult提供这样的所选音频文件的Uri:
content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Forganfinale.mp3
在Android(Lollipop)上,使用光标将uri转换为真实路径的效果很好,但是对于Oreo设备,我无法从此音频的Uri获取真实路径。
答案 0 :(得分:1)
我解决了。只需调用此getPathFromURI方法,它将返回文件路径
object RealPathHelper {
private const val BUFFER_SIZE = 1024 * 2
@TargetApi(Build.VERSION_CODES.O)
fun getPathFromURI(
context: Context,
contentUri: Uri,
fileNamePrefix: String,
defaultFileExtension: String
): String? {
val uriPath: String = contentUri.path ?: return null
val fileName: String = MediaFileHelper.getFileNameWithExtension(uriPath)
if (fileName.isNotBlank()) {
val destFile =
createOutputFile(context, contentUri, fileNamePrefix, defaultFileExtension)
copyUriToFile(context, contentUri, destFile)
return destFile.absolutePath
}
return null
}
private fun createOutputFile(
context: Context,
contentUri: Uri,
fileNamePrefix: String,
defaultFileExtension: String
): File {
var count = 0
var file: File
val uriPath: String? = contentUri.path
val fileExtension = if (uriPath == null) defaultFileExtension
else MediaFileHelper.getFileExtension(uriPath)
do {
count++
val mFileName = "$fileNamePrefix${StringHelper.getUniqueId()}$count$fileExtension"
val newFilePath =
"${context.getExternalFilesDir(null)?.absolutePath}${context.getString(R.string.audio_select_directory)}/$mFileName"
file = File(newFilePath)
} while (file.exists() && !file.isDirectory)
return file
}
private fun copyUriToFile(context: Context, srcUri: Uri, dstFile: File) {
try {
val inputStream = context.contentResolver.openInputStream(srcUri) ?: return
val outputStream = FileOutputStream(dstFile)
inputStream.copyTo(outputStream, BUFFER_SIZE)
inputStream.close()
outputStream.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
答案 1 :(得分:1)
由于文件路径在API 29及更高版本中无法用于公共文件,我建议您不要尝试使用它们,而应使用Java FileDescriptor
。
按照https://developer.android.com/training/data-storage#scoped-storage
更具体地说https://developer.android.com/training/data-storage/shared/media#open-file-descriptor
许多API允许您提供FileDescriptor
而不是路径。
代替
要从URI中获取fileDescriptor
,请执行以下操作(在Java中)
ParcelFileDescriptor pfd =
this.getContentResolver().
openFileDescriptor(URI, "r");
FileDescriptor fileDescriptor = pfd.getFileDescriptor();
答案 2 :(得分:0)
我通常使用该类来获取路径,您可以看一下该类几乎适用于所有版本
from ipywidgets import interact, Dropdown
geo = {'USA':['CHI','NYC'],'Russia':['MOW','LED']}
geo2={'CHI':['1','2'],'NYC':['3','4'],'MOW':['5','6'],'LED':['7','8']}
countryW = Dropdown(options = geo.keys())
cityW = Dropdown(options = geo[countryW.value]) # options = geo[countryW.value] is to remove inital error but not that necessary.
districtW = Dropdown()
@interact(country = countryW, city = cityW, district = districtW)
def print_city(country, city, district):
cityW.options = geo[country] # Here is the trick, i.e. update cityW.options based on country, namely countryW.value.
districtW.options = geo2[city] # Dittoo
print(country, city, district)