final String AUTHORITY = "com.android.externalstorage.documents";
Uri roottree = DocumentsContract.buildTreeDocumentUri(AUTHORITY,"primary:");
Uri sourceuri = DocumentsContract.buildDocumentUriUsingTree(roottree,DocumentsContract.geTreeDocumentId(roottree) + "Folder1");
Uri TargetUri = DocumentsContract.buildDocumentUriUsingTree(roottree,DocumentsContract.getTreeDocumentId(roottree) + "Folder2");
Uri resulturi = DocumentsContract.copyDocument(myContentResolver,sourceuri,TargetUri);
Copying Folder1 into Folder2 always return null. CreateDocument, DeleteDocument even MoveDocument working without any issue.
I believe it was a deliberately bug.
It didn't work and you need to rebuild the function.
Here is simple sample:
public boolean copyFileUri(Uri FilePath, Uri ToFolder, String Name){boolean done=true;
try {
InputStream in = this.getContentResolver().openInputStream(FilePath);
Uri uriOut=DocumentsContract.createDocument(getContentResolver(), ToFolder, "text/plain", Name );
OutputStream out = new FileOutputStream(getContentResolver().openFileDescriptor(uriOut, "w").getFileDescriptor());
Uri uRename=DocumentsContract.renameDocument(getApplicationContext().getContentResolver(), uriOut, Name );
if (uRename==null){/*RENAME WITH WHILE COUNTER*/}
try { byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } } catch(Exception e){done=false;}
out.close(); in.close();
} catch(Exception e){done=false;} return done;
}
Note that you will need to DIY additional function for these case:
The destination folder have files with the same name, you need to add counter for rename or a switch to overwrite old file.
If you want to copy folder, it will a little more complex by add:
Detect Uri was folder or normal file
Create folder
Scan File
Recursion calling itself when scan so it scan whole the tree.
Related
I'm implementing a file browser feature in my app. I know how to gain persistent permission for the external sd card using the ACTION_OPEN_DOCUMENT_TREE intent and how to create folders and delete files/folders using the DocumentFile class.
I can't however find a way to copy/move a file to an external sd card folder. Can you point me to the right direction ?
I have figured it out using lots of examples on SO. My solution for music files:
private String copyFile(String inputPath, String inputFile, Uri treeUri) {
InputStream in = null;
OutputStream out = null;
String error = null;
DocumentFile pickedDir = DocumentFile.fromTreeUri(getActivity(), treeUri);
String extension = inputFile.substring(inputFile.lastIndexOf(".")+1,inputFile.length());
try {
DocumentFile newFile = pickedDir.createFile("audio/"+extension, inputFile);
out = getActivity().getContentResolver().openOutputStream(newFile.getUri());
in = new FileInputStream(inputPath + inputFile);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
// write the output file (You have now copied the file)
out.flush();
out.close();
} catch (FileNotFoundException fnfe1) {
error = fnfe1.getMessage();
} catch (Exception e) {
error = e.getMessage();
}
return error;
}
I am making a soundboard for practice and I want to give the user the ability to download the sound (that I have included in the app in the res/raw folder) onClick of a menu item but I can only find information about downloading from an internet url, not something that I already included in the apk.
What is the best way to do this? I would like to give them the option to save to an SD card also if this is possible. A point towards the correct class to use in the documentation would be great! I've been googling to no avail.
Thanks!
Try something like this:
public void saveResourceToFile() {
InputStream in = null;
FileOutputStream fout = null;
try {
in = getResources().openRawResource(R.raw.test);
String downloadsDirectoryPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
String filename = "myfile.mp3"
fout = new FileOutputStream(new File(downloadsDirectoryPath + filename));
final byte data[] = new byte[1024];
int count;
while ((count = in.read(data, 0, 1024)) != -1) {
fout.write(data, 0, count);
}
} finally {
if (in != null) {
in.close();
}
if (fout != null) {
fout.close();
}
}
}
I don't know about the raw but I did a similar thing in my app using the assets folder. My files are under the assets/backgrounds folder as you can probably guess from the code below.
You can modify this code and make it work for you (I know I will only have 4 files which is why I have i go from 0 to 4 but you can change this to whatever you want).
This code copies the file starting with prefix_ (like prefix_1.png, prefix_2.png, etc) to my cache directory but you can obviously change the extension, the filename or the path you would like to save the assets to.
public static void copyAssets(final Context context, final String prefix) {
for (Integer i = 0; i < 4; i++) {
String filename = prefix + "_" + i.toString() + ".png";
File f = new File(context.getCacheDir() + "/" + filename);
if (f.exists()) {
f.delete();
}
if (!f.exists())
try {
InputStream is = context.getAssets().open("backgrounds/" + filename);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
FileOutputStream fos = new FileOutputStream(f);
fos.write(buffer);
fos.close();
} catch (Exception e) {
Log.e("Exception occurred while trying to load file from assets.", e.getMessage());
}
}
}
I'm writing app for android and I'm using caffe library. My problem is that on start I need to initialize caffe, which is done by passing two files (structures of network) to caffe.
Problem is that I don't know how to store extra files on device. I've added model file to assets, but I don't know how can I read it using file path. Can you tell me where to store these file that could be access using file path?
Thanks for any ideas.
This should do it. Just copy those files to data directory from asset folder. If you already have those files there just load them.
String toPath = "/data/data/" + getPackageName(); // Your application path
private static boolean copyAssetFolder(AssetManager assetManager,
String fromAssetPath, String toPath) {
try {
String[] files = assetManager.list(fromAssetPath);
new File(toPath).mkdirs();
boolean res = true;
for (String file : files)
if (file.contains("."))
res &= copyAsset(assetManager,
fromAssetPath + "/" + file,
toPath + "/" + file);
else
res &= copyAssetFolder(assetManager,
fromAssetPath + "/" + file,
toPath + "/" + file);
return res;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean copyAsset(AssetManager assetManager,
String fromAssetPath, String toPath) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(fromAssetPath);
new File(toPath).createNewFile();
out = new FileOutputStream(toPath);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
return true;
} catch(Exception e) {
e.printStackTrace();
return false;
}
}
private static void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
Put them into your project as assets, and then when the app starts, you can read them from the assets and copy them into the app's private storage area. You can find this directory using Context.getFilesDir().
From there, you'll be able to pass the files to Caffe.
Assets are packaged and access only using special methods, so i solved problem by access file and then copy it to new location which i passed to native method.
I am making an android webview application,there are a lot of files such as js/css/images must be downloaded from CDN to the app, because the network is not stable in our region and the size of the cached files is much bigger than the app itself, is there some way to build the apk file with the cache files stored automatically when the app runs at first few times.
Put your files and folders to assets. you'll find it in your project directory. When your application runs copy all assets contents to your SD card. then run your app :)
If you need any help about how to copy assets content to SD card let me know.
Copy Assets contents to SD card
Bellow code will copy all the contents of specified folder of your assets to your specified location of your SD card
CopyAssetContents.java
public class CopyAssetContents {
public static boolean copyAssetFolder(AssetManager assetManager,String fromAssetPath, String toPath) {
try {
String[] files = assetManager.list(fromAssetPath);
new File(toPath).mkdirs();
boolean res = true;
for (String file : files)
if (file.contains("."))
res &= copyAsset(assetManager,
fromAssetPath + "/" + file,
toPath + "/" + file);
else
res &= copyAssetFolder(assetManager,
fromAssetPath + "/" + file,
toPath + "/" + file);
return res;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean copyAsset(AssetManager assetManager,
String fromAssetPath, String toPath) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(fromAssetPath);
new File(toPath).createNewFile();
out = new FileOutputStream(toPath);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
return true;
} catch(Exception e) {
e.printStackTrace();
return false;
}
}
private static void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
}
For example you have all your contents in a folder named "CONTENTS" inside of your assets.and want to copy all of its content to root of your SD card.
call bellow method.
CopyAssetContents.copyAssetFolder(getAssets(), "CONTENTS", Environment.getExternalStorageDirectory().getAbsolutePath());
Official facebook App has a bug, when you try to share an image with share intent, the image gets deleted from the sdcard. This is the way you have to pass the image to facebook app using the uri of the image:
File myFile= new File(Environment.getExternalStorageDirectory(), "car.jpg");
Uri uri = Uri.fromFile(myFile);
i.putExtra(Intent.EXTRA_STREAM, uri);
Then, suppose that if i create a copy from the original myFile object, and i pass the uri of the copy to facebook app, then, my original image will not be deleted.
I tried with this code, but it doesn't work, the original image file is still getting deleted:
File myFile= new File(Environment.getExternalStorageDirectory(), "car.jpg");
File auxFile=myFile.getAbsoluteFile();
Uri uri = Uri.fromFile(auxFile);
Can someone tell me how to do a exact copy of a file that doesn't redirect to the original File?
Please check: Android file copy
The file is copied byte by byte so no reference to the old file is maintained.
Here, this should be able to create a copy of your file:
private void CopyFile() {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(<file path>);
out = new FileOutputStream(<output path>);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch(Exception e) {
Log.e("tag", e.getMessage());
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}