Implicit Intentから取得している既存のURIからメディアファイル(たとえば.mp3)を保存するにはどうすればよいですか?
9 に答える
この方法を使用すると、機能します
void savefile(URI sourceuri)
{
String sourceFilename= sourceuri.getPath();
String destinationFilename = android.os.Environment.getExternalStorageDirectory().getPath()+File.separatorChar+"abc.mp3";
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(sourceFilename));
bos = new BufferedOutputStream(new FileOutputStream(destinationFilename, false));
byte[] buf = new byte[1024];
bis.read(buf);
do {
bos.write(buf);
} while(bis.read(buf) != -1);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bis != null) bis.close();
if (bos != null) bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static String FILE_NAM = "video";
String outputfile = getFilesDir() + File.separator+FILE_NAM+"_tmp.mp4";
InputStream in = getContentResolver().openInputStream(videoFileUri);
private static File createFileFromInputStream(InputStream inputStream, String fileName) {
try {
File f = new File(fileName);
f.setWritable(true, false);
OutputStream outputStream = new FileOutputStream(f);
byte buffer[] = new byte[1024];
int length = 0;
while((length=inputStream.read(buffer)) > 0) {
outputStream.write(buffer,0,length);
}
outputStream.close();
inputStream.close();
return f;
} catch (IOException e) {
System.out.println("error in creating a file");
e.printStackTrace();
}
return null;
}
UriがGoogleドライブから受信された場合、それは仮想ファイルUriでもあります。詳細については、CommonsWareのこの記事を確認してください。したがって、URIからファイルを保存するときは、その条件も考慮する必要があります。
ファイルUriが仮想であるかどうかを確認するには、次を使用できます。
private static boolean isVirtualFile(Context context, Uri uri) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (!DocumentsContract.isDocumentUri(context, uri)) {
return false;
}
Cursor cursor = context.getContentResolver().query(
uri,
new String[]{DocumentsContract.Document.COLUMN_FLAGS},
null, null, null);
int flags = 0;
if (cursor.moveToFirst()) {
flags = cursor.getInt(0);
}
cursor.close();
return (flags & DocumentsContract.Document.FLAG_VIRTUAL_DOCUMENT) != 0;
} else {
return false;
}
}
この仮想ファイルから次のようにストリームデータを取得できます。
private static InputStream getInputStreamForVirtualFile(Context context, Uri uri, String mimeTypeFilter)
throws IOException {
ContentResolver resolver = context.getContentResolver();
String[] openableMimeTypes = resolver.getStreamTypes(uri, mimeTypeFilter);
if (openableMimeTypes == null || openableMimeTypes.length < 1) {
throw new FileNotFoundException();
}
return resolver
.openTypedAssetFileDescriptor(uri, openableMimeTypes[0], null)
.createInputStream();
}
MIMEタイプを見つけるには、
private static String getMimeType(String url) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
return type;
}
全体的に、あなたは使用することができます
public static boolean saveFile(Context context, String name, Uri sourceuri, String destinationDir, String destFileName) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
InputStream input = null;
boolean hasError = false;
try {
if (isVirtualFile(context, sourceuri)) {
input = getInputStreamForVirtualFile(context, sourceuri, getMimeType(name));
} else {
input = context.getContentResolver().openInputStream(sourceuri);
}
boolean directorySetupResult;
File destDir = new File(destinationDir);
if (!destDir.exists()) {
directorySetupResult = destDir.mkdirs();
} else if (!destDir.isDirectory()) {
directorySetupResult = replaceFileWithDir(destinationDir);
} else {
directorySetupResult = true;
}
if (!directorySetupResult) {
hasError = true;
} else {
String destination = destinationDir + File.separator + destFileName;
int originalsize = input.available();
bis = new BufferedInputStream(input);
bos = new BufferedOutputStream(new FileOutputStream(destination));
byte[] buf = new byte[originalsize];
bis.read(buf);
do {
bos.write(buf);
} while (bis.read(buf) != -1);
}
} catch (Exception e) {
e.printStackTrace();
hasError = true;
} finally {
try {
if (bos != null) {
bos.flush();
bos.close();
}
} catch (Exception ignored) {
}
}
return !hasError;
}
private static boolean replaceFileWithDir(String path) {
File file = new File(path);
if (!file.exists()) {
if (file.mkdirs()) {
return true;
}
} else if (file.delete()) {
File folder = new File(path);
if (folder.mkdirs()) {
return true;
}
}
return false;
}
AsycTaskからこのメソッドを呼び出します。これが役立つかどうか教えてください。
次のコードを使用して、インテントからアプリがホストするUriに返された既存のUriからファイルを保存しました。
private void copyFile(Uri pathFrom, Uri pathTo) throws IOException {
try (InputStream in = getContentResolver().openInputStream(pathFrom)) {
if(in == null) return;
try (OutputStream out = getContentResolver().openOutputStream(pathTo)) {
if(out == null) return;
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
}
}
}
これが最も簡単でクリーンな方法です。
private void saveFile(Uri sourceUri, File destination)
try {
File source = new File(sourceUri.getPath());
FileChannel src = new FileInputStream(source).getChannel();
FileChannel dst = new FileOutputStream(destination).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
android.net.Uri
外部ソースからを受信する場合、ファイルを保存する最良の方法はストリームからです。
try (InputStream ins = activity.getContentResolver().openInputStream(source_uri)) {
File dest = new File(destination_path);
createFileFromStream(ins, dest);
} catch (Exception ex) {
Log.e("Save File", ex.getMessage());
ex.printStackTrace();
}
createFileFromStream
方法:
public static void createFileFromStream(InputStream ins, File destination) {
try (OutputStream os = new FileOutputStream(destination)) {
byte[] buffer = new byte[4096];
int length;
while ((length = ins.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
os.flush();
} catch (Exception ex) {
Log.e("Save File", ex.getMessage());
ex.printStackTrace();
}
}
1.次のようにURIパスからファイルを作成します。
File from = new File(uri.toString());
2.ファイルを次のように保存する場所に別のファイルを作成します。
File to = new File("target file path");
3.ファイルの名前を次のように変更します。
from.renameTo(to);
これにより、デフォルトパスのファイルが自動的に削除され、新しいパスに作成されます。
外部保存場所を取得してファイルを保存する方法
この答えは質問ではなく、タイトルです。プロセスを完全に説明している記事はないため、これを行う方法を理解するのに何時間もかかりましたが、一部の記事は古く、非推奨のAPIを使用しています。これが将来の開発者に役立つことを願っています。
外部ストレージの場所を取得する
たとえば、フラグメントの内側から、
// when user choose file location
private val uriResult = registerForActivityResult(ActivityResultContracts.CreateDocument()) { uri ->
// do when user choose file location
createFile(uri)
}
fun openFileChooser() {
// startActivityForResult() is deprecated
val suggestedFileName = "New Document.txt"
uriResult.launch(suggestedFileName)
}
URIを使用してファイルデータを書き込む
をに変換する直接的な方法がないため、java.io.File
からを作成するのは難しいように思われるかもしれません。しかし、あなたが持っているなら、あなたはそれを非常に簡単に行うことができます。android.net.Uri
android.net.Uri
java.net.URI
ApplicationContext
fun createFile(uri: Uri) {
try {
requireContext().applicationContext.contentResolver.openFileDescriptor(uri, "w")?.use { fd ->
FileOutputStream(fd).use { fos ->
// do your job on the FileOutputStream
// also use background thread
fos.close()
}
}
} catch (e: Exception) {
}
}
注:ファイル操作は複数の例外をスローするため、慎重に処理してください。また、ワーカースレッドでファイル操作を行います。
あなたはそれを使用してそれを行うことができます
new File(uri.getPath());