私のアプリでは、ユーザーが音声ファイルを選択して、アプリで処理します。問題は、アプリがオーディオファイルで必要な処理を行うために、URIがファイル形式である必要があることです。 Androidのネイティブミュージックプレーヤーを使用してアプリでオーディオファイルを参照する場合、URIは次のようなコンテンツURIです。
content://media/external/audio/media/710
ただし、一般的なファイルマネージャーアプリケーションAstroを使用すると、次の結果が得られます。
file:///sdcard/media/audio/ringtones/GetupGetOut.mp3
後者の方がずっと使いやすいですが、もちろん、コレクションの閲覧に使用するプログラムに関係なく、ユーザーが選択したオーディオファイルの機能をアプリに持たせたいです。私の質問は、content://
スタイルURIをfile://
URIに変換する方法はありますか?そうでなければ、この問題を解決するために私に何をお勧めしますか?参照用にチューザーを呼び出すコードは次のとおりです。
Intent ringIntent = new Intent();
ringIntent.setType("audio/mp3");
ringIntent.setAction(Intent.ACTION_GET_CONTENT);
ringIntent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(ringIntent, "Select Ringtone"), SELECT_RINGTONE);
コンテンツURIで次のことを行います。
m_ringerPath = m_ringtoneUri.getPath();
File file = new File(m_ringerPath);
次に、上記のファイルを使用してFileInputStreamを実行します。
getContentResolver().openInputStream(uri)
を使用して、URIからInputStream
を取得します。
コンテンツリゾルバーを使用して、file://
URIからcontent://
パスを取得できます。
String filePath = null;
Uri _uri = data.getData();
Log.d("","URI = "+ _uri);
if (_uri != null && "content".equals(_uri.getScheme())) {
Cursor cursor = this.getContentResolver().query(_uri, new String[] { Android.provider.MediaStore.Images.ImageColumns.DATA }, null, null, null);
cursor.moveToFirst();
filePath = cursor.getString(0);
cursor.close();
} else {
filePath = _uri.getPath();
}
Log.d("","Chosen path = "+ filePath);
content://com.externalstorage...
のコンテンツUriがある場合、このメソッドを使用して、フォルダーまたはファイルの絶対パスを取得できますAndroid 19以上。
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
System.out.println("getPath() uri: " + uri.toString());
System.out.println("getPath() uri authority: " + uri.getAuthority());
System.out.println("getPath() uri path: " + uri.getPath());
// ExternalStorageProvider
if ("com.Android.externalstorage.documents".equals(uri.getAuthority())) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
System.out.println("getPath() docId: " + docId + ", split: " + split.length + ", type: " + type);
// This is for checking Main Memory
if ("primary".equalsIgnoreCase(type)) {
if (split.length > 1) {
return Environment.getExternalStorageDirectory() + "/" + split[1] + "/";
} else {
return Environment.getExternalStorageDirectory() + "/";
}
// This is for checking SD Card
} else {
return "storage" + "/" + docId.replace(":", "/");
}
}
}
return null;
}
Uriの各部分がprintlnを使用していることを確認できます。 SDカードとデバイスのメインメモリの戻り値は以下のとおりです。ファイルがメモリ上にある場合にアクセスして削除できますが、この方法を使用してSDカードからファイルを削除できなかった場合、この絶対パスを使用してイメージを読み取りまたは開くことができます。この方法を使用して削除するソリューションを見つけた場合は、共有してください。 SDカード
getPath() uri: content://com.Android.externalstorage.documents/tree/612E-B7BF%3A/document/612E-B7BF%3A
getPath() uri authority: com.Android.externalstorage.documents
getPath() uri path: /tree/612E-B7BF:/document/612E-B7BF:
getPath() docId: 612E-B7BF:, split: 1, type: 612E-B7BF
メインメモリー
getPath() uri: content://com.Android.externalstorage.documents/tree/primary%3A/document/primary%3A
getPath() uri authority: com.Android.externalstorage.documents
getPath() uri path: /tree/primary:/document/primary:
getPath() docId: primary:, split: 1, type: primary
パスを取得した後にfile:///
でUriを取得する場合
DocumentFile documentFile = DocumentFile.fromFile(new File(path));
documentFile.getUri() // will return a Uri with file Uri
ContentResolver.query()
を呼び出してcontent://スキームでURIを処理しようとすることは、良い解決策ではありません。 4.2.2を実行しているHTC Desireでは、クエリ結果としてNULLを取得できます。
代わりにContentResolverを使用しないのはなぜですか? https://stackoverflow.com/a/29141800/3205334
まあ私は少し答えるのが遅れていますが、私のコードはテストされています
uriからスキームをチェックします:
byte[] videoBytes;
if (uri.getScheme().equals("content")){
InputStream iStream = context.getContentResolver().openInputStream(uri);
videoBytes = getBytes(iStream);
}else{
File file = new File(uri.getPath());
FileInputStream fileInputStream = new FileInputStream(file);
videoBytes = getBytes(fileInputStream);
}
上記の答えでは、ビデオuriをバイト配列に変換しましたが、それは質問とは関係ありません。コードでFileInputStream
とInputStream
の両方が同じように機能するため、コード全体をコピーして。
私のフラグメントではgetActivity()である変数コンテキストを使用し、アクティビティでは単にActivityName.thisになります
context=getActivity();
//フラグメント内
context=ActivityName.this;
//アクティビティ中