I am trying to copy a file to another folder in the android, but so far, i got no success. I manage to do so with a selected image and when taking a photo, but not with files.
I've read and tried several solutions passed by the community (searched over the forum and the internet), but none of it was able to solve my problem when copying.
First things first. I added the permissions to my manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
after that, before copying a file, i print its filepath and the directory file path:
06-10 11:11:11.700: I/System.out(1442): /mimetype/storage/sdcard/Misc/Javascript erros for Submit and Plan buttons in IE.doc
06-10 11:11:11.710: I/System.out(1442): /storage/sdcard/files/queue
both exists:
to copy the file to the expected folder I used the FileUtils:
try {
FileUtils.copyFile(selectedFile, dir);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The problem is: I get no exception and the file isn't there. I tried this solution either:
How to move/rename file from internal app storage to external storage on Android?
same thing, no exception, but no file either.
**Edited**
This is how I get the file.
Uri uri = data.getData();
File selectedFile = new File(uri.getPath());
File dir = new File(Environment.getExternalStorageDirectory(), "files/queue");
To get the image, I do this way:
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(selectedImage,filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
saveChecklistImage(BitmapFactory.decodeFile(picturePath));
I retrieve the file here when I call BitmapFactory.decodeFile(picturePath), then, I save it without a problem.
Should file follow this standard as well?
**Solution**
I found out a way to do so in this post:
android get real path by Uri.getPath()
Specifically this method:
private String getRealPathFromURI(Uri contentURI) {
String result;
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) { // Source is Dropbox or other similar local file path
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
kind of same thing i was doing with image, but in a much smarter way ;D
easier than I tought.
Thanks for the helpers
If argument 2 is a directory you should be using copyFileToDirectory.
copyFile() doesn't take directory as a 2nd parameter (see here). It takes file (as source) and file (as destination). Create an empty file first:
File file = new File(dir+"/newfile.doc");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
Use that instead of dir. Or use Travis' way. Also replace [space] with _ in your filenames.
Related
I tried to move a photo taken by the camera to a folder named "raspberrypi" I created. But the .renameTo() keeps returning false. I cannot find the reason. To clarify, the photos I am trying to move are taken by the camera, so they aren't in any folder to begin with.
imagesEncodedList is an ArrayList of File path Strings.
boolean bool=false;
for(int i=0; i<imagesEncodedList.size();i++){
File from;
File to=null;
try{
from=new File(imagesEncodedList.get(i));
String dateString=new SimpleDateFormat("MM_dd_yyyy_HH:mm:ss").format(Calendar.getInstance().getTime());
to=new File(getPublicDir(),"SideBySide4_ImportedPhoto"+i+"_"+dateString+".jpg");
bool=from.renameTo(to);
}catch(Exception e){
e.printStackTrace();
}
MediaScannerConnection.scanFile(this,
new String[]{to.getPath()},
null,
null);
}
Toast.makeText(this, "Success?: "+bool, Toast.LENGTH_LONG)
.show();
Here is my getPublicDir() function implementation:
public File getPublicDir() {
// Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "raspberry");
if (!file.mkdirs()) {
Log.e("PUBLIC DIRECTORY", "Directory not created");
}
return file;
}
renameTo only works if source and target are on the same disk partition. If they're not, you'll have to copy the source file and delete it afterwards.
context.getFilesDir() is on a different partition (/data) than Environment.getExternalStoragePublicDirectory (typically accessible under /sdcard).
I'm new to Android Studio 3.0, emulating on a Nexus 4, Marshmallow. I'm trying to build simple "Save File" and "Load File" parts of my app. Here's the "Save File" part:
String filename = "myFile01"; // Then "myFile02", "myFile03", etc...
String userData = "Some useful data here...";
try {
// Adapted from: https://www.youtube.com/watch?v=_15mKw--RG0
FileOutputStream fileOutputStream = openFileOutput(filename, MODE_PRIVATE); // creates a file with given filename
fileOutputStream.write(userData.getBytes()); // puts userData into the file
fileOutputStream.close();
Toast.makeText(getApplicationContext(), "File saved!", Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
The above code will be called again and again as the user creates and saves additional files. Later, the user may want to view all the saved files and load one. I'll have a ListView displaying all the files... but I need help reading the current directory to get that list.
I thought I read somewhere that in Android, there's one flat directory for your app to save and retrieve files. So I was hoping if I saved a bunch of files and then called a read() method, all my saved files would simply be in the default directory, no need to search. That seems to be a bad assumption; here's why:
Here's my code looking in the default directory and listing all the files found within there. First, I need the path of said default directory:
// Get current directory adapted from: https://stackoverflow.com/questions/5527764/get-application-directory
String packName, currDir;
PackageManager m = getPackageManager();
packName = getPackageName();
PackageInfo p = null;
try {
p = m.getPackageInfo(packName, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
currDir = p.applicationInfo.dataDir;
And then I open "currDir," and store the names of all the local files in an array:
// get list of files adapted from: https://stackoverflow.com/questions/9317483/showing-a-list-of-files-in-a-listview#9317583
File dir = new File(currDir);
File[] filelist = dir.listFiles();
String[] fileArr = new String[filelist.length];
for (int i = 0; i < fileArr.length; i++) {
fileArr[i] = filelist[i].getName();
}
The plan from here is to load the "fileArr" into a ListView and go from there. But when I step through the debugger, I see this as the contents of "fileArr":
"cache"
"code_cache"
"files"
This is true no matter how many files I've saved previously.
BTW, in the debugger, the assignments for packName and currDir look 100% correct:
packName = com.mydomain.myapp
currDir = /data/user/0/com.mydomain.myapp
So... I'm kinda assuming that my saved files are actually here:
/data/user/0/com.mydomain.myapp/files
And therefore, I should append this to my "get current directory" code:
// Get current directory adapted from: https://stackoverflow.com/questions/5527764/get-application-directory
String packName, currDir;
...everything from before...
currDir = p.applicationInfo.dataDir+"/files"; // <---- appending "+"/files"
Or am I way off? Any advice will be appreciated, thanks!
First of all, if you want to save your files in the app's directory, then you should call create a directory,
File directoryDefault = new File(Environment.DIRECTORY_DOCUMENTS, "YOUR_FOLDER_NAME");
if (!directoryDefault.exists()) {
directoryDefault.mkdir();
}
Then you have to save whatever files you have to save in the above mentioned default directory. Afterwards, when you want to list all the files available in that directory, you should call,
private ArrayList<String> fileNames() {
ArrayList<String> namesArray = new ArrayList<>();
File[] arrayFiles = directoryDefault.listFiles();
for (File file : arrayFiles) {
namesArray.add(file.getName());
}
return namesArray;
}
I have tried numerous methods of getting a file object from a google drive URI but most result in the following error:
java.lang.SecurityException: Permission Denial: reading com.google.android.apps.docs.storagebackend.StorageBackendContentProvider uri content://com.google.android.apps.docs.storage/document/acc=1;doc=4235 from pid=32140, uid=10149 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()
So I added android.permission.MANAGE_DOCUMENTS and it did not work, so I tried to use grantUriPermission() and got the following error:
java.lang.SecurityException: Uid 10151 does not have permission to uri 0 # content://com.google.android.apps.docs.storage/document/acc=1;doc=4235
This file plugin has a nice way of getting files from just about anywhere, except google drive: aFileChooser.
So I took to stack overflow for answers:
Open a Google Drive File Content URI after using KitKat Storage Access Framework
Android KitKat securityException when trying to read from MediaStore
Getting Permission Denial Exception
No permission for UID to access URI error on Android Application
and there are about 15 others, but none helped
I am using Cordova so this is a cross platform app so it restricts me a bit. Here is how I get my URI, I press a button in my webview app, and then a new page is loaded allowing me to select my video from somewhere on my phone and I select google drive, then select a video, and then a URI is sent back to my webview I was on, I then send the URI to a java file to try and download the file. here is the different methods I have tried to download the file:
String filePath = null;
Log.d(TAG,"URI = "+ uri);
if (uri != null && "content".equals(uri.getScheme())) {
Log.d(TAG, "got inside if");
Cursor cursor = context.getContentResolver().query(uri, new String[] { android.provider.MediaStore.Files.FileColumns.DATA }, null, null, null);
cursor.moveToFirst();
filePath = cursor.getString(0);
cursor.close();
} else {
Log.d(TAG, "got inside else");
filePath = uri.getPath();
}
Log.d("","Chosen path = "+ filePath);
This method is similar, but fails the same:
String mimeType = context.getContentResolver().getType(uri);
Log.d(TAG,mimeType);
Cursor returnCursor = getContentResolver().query(returnUri, null, null, null, null);
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
returnCursor.moveToFirst();
Log.d(TAG,returnCursor.getString(nameIndex));
Log.d(TAG,Long.toString(returnCursor.getLong(sizeIndex)));
This method game the same error as the previous
try{
InputStream input = context.getContentResolver().openInputStream(uri);
try {
File file = new File(context.getCacheDir(), "cacheFileAppeal.mp4");
OutputStream output = new FileOutputStream(file);
try {
try {
byte[] buffer = new byte[4 * 1024]; // or other buffer size
int read;
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
} finally {
output.close();
}
} catch (Exception e) {
e.printStackTrace(); // handle exception, define IOException and others
}
} finally {
input.close();
}
}
catch(Exception e){
e.printStackTrace();
}
all three game me
java.lang.SecurityException: Permission Denial: reading com.google.android.apps.docs.storagebackend.StorageBackendContentProvider uri content://com.google.android.apps.docs.storage/document/acc=1;doc=4235 from pid=32140, uid=10149 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()
The following code for some reason did not crash, but gave me the mimeType:
String mimeType = context.getContentResolver().getType(uri);
I think the problem is that I am not using the URI in the original intent where the URI was retrieved from google drive, but I am not sure.
Does anyone know how to get a file object from google drive URI?
this question has been asked before(not specifically like this) but there hasn't been an All Exclusive answer to it yet. so we are trying to find the best solution here. i'm developing an app and in my app i hide a directory named myPic by moving it's files to a directory called .myPic. when i hide my pictures it's thumbnails are still in gallery. i find 3 solution to this:
first solution:
using ACTION_MEDIA_MOUNTED broad cast like this:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
the problem with this code is that it takes hug resources and most importantly it is blocked since android 4.4. so using this method is not rational for adding 10 pictures to gallery. so it is not an All exclusive method. also using ACTION_MEDIA_SCANNER_SCAN_FILE doesn't work on android 4.4 either
second solution:
using MediaScannerConnection. so i created a for loop and pass the old address of every file that i hide. this is my MediaScannerConnection function:
private void scanFile(File file) {
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this,new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
}
the thing about MediaScannerConnection is that it only effect if the file exist. so lets say i have a picture called 1.jpg in myPic directory. using this class i can add 1.jpg to my gallery immediately but when i move 1.jpg to .myPic directory and i scan the old path of 1.jpg nothing happen. logcat says that this file doen't exsit. so MediaScannerConnection only add files to gallery. what if i pass the new path of 1.jpg to MediaScannerConnection? well it adds 1.jpg from .myPic directory to gallery and that is exactly not what i want. so again not an All Exclusive method
third solution:
using getContentResolver(). so for deleting thumbnails this method may be the ultimate solution. so i write the blow code. in every loop i retrieve the path of image and pass it to getContentResolver().delete(Uri.parse(path),null,null). here is the code:
File myPic = new File(Environment.getExternalStorageDirectory()+"/myPic");
File myPicHide = new File(Environment.getExternalStorageDirectory()+"/.myPic");
if (!(myPicHide.exists()) & !(myPicHide.isDirectory())) {
myPicHide.mkdirs();
};
if (myPic.isDirectory()) {
String[] childeren = myPic.list();
if (childeren.length > 0) {
for (int i = 0; i < childeren.length; i++) {
String fileName = childeren[i];
File from = new File(Environment.getExternalStorageDirectory()+"/myPic"+fileName);
File to = new File(Environment.getExternalStorageDirectory()+"/.myPic"+fileName);
from.renameTo(to);
try {
String path = from.toString();
getContentResolver().delete(Uri.parse(path),null,null);
} catch(Exception e) {
Log.d("Rename", "Error happened");
}
}
}
} else {
Toast.makeText(getApplicationContext(), "myPic directory not found", Toast.LENGTH_LONG).show();
}
but it's not working either and thumbnails of my files are still showed in galley. so am i using getContentResolver() in wrong way?? this might be the all Exclusive method for the situation where deleted files thumbnails show up in gallery. i have my files path and i need to only delete it from media store content provider.
update:
so turns out that using Uri.parse(path) in the third solution is wrong. image Uri is started with content:// and it can be retrieved by MediaScannerConnection. so i created a Uri called imageInGalleryUri and assign null value to it. using my scanFile function i changed it's value from time to time and pass it's value to getContentResolver(). here is the code:
boolean whereIsMediaState = true;
Uri imageInGalleryUri = null;
File myPic = new File(Environment.getExternalStorageDirectory()+"/myPic");
File myPicHide = new File(Environment.getExternalStorageDirectory()+"/.myPic");
if (!(myPicHide.exists()) & !(myPicHide.isDirectory())) {
myPicHide.mkdirs();
};
if (myPic.isDirectory()) {
String[] childeren = myPic.list();
if (childeren.length > 0) {
for (int i = 0; i < childeren.length; i++) {
String fileName = childeren[i];
File from = new File(Environment.getExternalStorageDirectory()+"/myPic"+fileName);
scanFile(from);
File to = new File(Environment.getExternalStorageDirectory()+"/.myPic"+fileName);
from.renameTo(to);
if (to.isFile()){
try {
getContentResolver().delete(imageInGalleryUri,null,null);}
catch(Exception e) {
Log.d("Rename", "Error happened");
}
}
}
} else {
Toast.makeText(getApplicationContext(), "myPic directory not found", Toast.LENGTH_LONG).show();
}
private void scanFile(File file) {
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this,new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
imageInGalleryUri = uri;
}
});
}
i tried the code but it only detect the first image and delete it from the gallery but does not effect the other images. i can't figure out why. any idea?
thank you for your help in advance
. before folder just make it invisible. But there is way to say don't use this folder at all to gallery.
Please try to put empty file called ".nomedia" file into your folder.
This is my function for converting blob to mp3:
private void convertByyeToMP3(byte[] bytearray,String trackName) {
try {
ContextWrapper c = new ContextWrapper(getApplicationContext());
File directory = new File(c.getFilesDir().getAbsolutePath()
+ "/Music");
if (!directory.exists()){
directory.mkdir();
}
File tempMp3 = File.createTempFile(trackName, ".mp3",
directory);
FileOutputStream fos = new FileOutputStream(tempMp3);
fos.write(bytearray);
fos.close();
Log.d("Byte array to mp3 conversion: ", "successfull");
} catch (Exception ex) {
Log.d("In convertToByteToMp3 Function:", ex.toString());
}
}
When I execute this function ,I can see the created mp3 files in my app folder but when I try to play them Using my own code or using ES File Explorer, they both can't play it.
This is the function I use play my music:
private MediaPlayer mp = new MediaPlayer();
private void playSong(String songPath) {
try {
mp.reset();
mp.setDataSource(songPath);
mp.prepare();
mp.start();
} catch (IOException e) {
Log.v(getString(R.string.app_name), e.getMessage());
}
}
And I use this sample code to play the track:
ContextWrapper c = new ContextWrapper(getApplicationContext());
File directory = new File(c.getFilesDir().getAbsolutePath() + "/Music");
playSong(directory.getPath() + File.separator + "kurchina");
This is where I read database and send the blob:
cursor = mDbHelper.GetTables();
byte[] blob = null;
DATAS data = new DATAS();
while (cursor.moveToNext()) {
blob = cursor.getBlob(cursor.getColumnIndex("data"));
if (blob != null) {convertByyeToMP3(blob,data_MusicName);}
db.addDATAS(data);
}
FYIs:
-Read and Write permissions added to manifest.
-Path and filename are check and they exist
-blob byte is not corrupted
There are all sorts of things that might have gone wrong, either in the code that you have shown us or elsewhere. So you need to do your own troubleshooting. Methodically.
Figure out if the problem is with the song file you have extracted or the way you are playing it. For example, try to play the extracted file using a free-standing mp3 player utility.
Assuming that the problem is the extracted file, the next thing is to figure out if the file is the same as the one that you originally inserted into the database. Compare the file sizes and the checksums using the relevant external applications.
and so on.
Found the problem.
It didn't play because the music files were stored in my app folder which is only accessible using a rooted device.
When I copied the music to my sdcard they played well, but in my app folder using rooted nexus 7 I couldn't play it even with an mp3-player app.