Trying for this Jave program to work on my android where the host is a Windows 64 bit machine. Have created a class and extended FFMPEGLocator class defining the path to the ffmpeg executable in my file system. But doesn't seem to work each time showing "error 13, permission denied". Could someone please put some light into this situation?
Class extended
class SampleLocator extends FFMPEGLocator {
#Override
protected String getFFMPEGExecutablePath() {
return "...\\bin\\ffmpeg.exe";
} }
audio converting code
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File source = new File(url);
targetFile = new File(path, "sample.wav");
AudioAttributes audio = new AudioAttributes();
audio.setCodec("pcm_s16le");
audio.setBitRate(64000);
audio.setChannels(2);
audio.setSamplingRate(44100);
EncodingAttributes attrs = new EncodingAttributes();
attrs.setFormat("wav");
attrs.setAudioAttributes(audio);
Encoder encoder = new Encoder(new MyDefaultFFMPEGLocator());
try {
encoder.encode(source, targetFile, attrs);
}
catch (IllegalArgumentException | InputFormatException e){
e.printStackTrace();
} catch (EncoderException e) {
e.printStackTrace();
}
So this is how I solved this Permission denied error. You first have to instantiate the ffmpeg executable file instance and then provide the execute permission code pointing the ffmpeg executable file path.
Used the help of this open source project
ffmpeg-android
Runtime.getRuntime().exec("chmod -R 777 " + ffmpeg.getAbsolutePath()).waitFor();
Related
I'm trying to copy file from within my application to the SD card, but I get the error eacces (permission denied). The OS is Android M and I have allowed runtime Storage permissions (checked in app info). I have also set the uses-permission in AndroidManifest.xml
<application>...</application>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Doesn't work if I copy to SD card
Source: data/user/0/com.example.myapp/cache/SomeFile.txt
Destination: /storage/1032-2568/SomeFolder/
Error: java.io.FileNotFoundException: /storage/1032-2568/SomeFolder/SomeFile.txt: open failed: EACCES (Permission denied)
Works if I copy to internal storage
Source: data/user/0/com.example.myapp/cache/SomeFile.txt
Destination: /storage/emulated/0/SomeFolder/
Code to copy file from source to destination
/*
* Below are the parameters I have tried
*
* inputPath - data/user/0/com.example.myapp/cache or data/user/0/com.example.myapp/cache/
* inputFile - /SomeFile.txt or SomeFile.txt
* outputPath - /storage/1032-2568/SomeFolder/ or /storage/1032-2568/SomeFolder
*/
public static void copyFile(String inputPath, String inputFile, String outputPath) {
InputStream in = null;
OutputStream out = null;
try {
//create output directory if it doesn't exist
File dir = new File (outputPath);
if (!dir.exists()) {
dir.mkdirs();
}
in = new FileInputStream(inputPath + inputFile);
out = new FileOutputStream(outputPath + 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) {
/* I get the error here */
Log.e("tag", fnfe1.getMessage());
}
catch (Exception e) {
Log.e("tag", e.getMessage());
}
}
ES File Explorer
I saw that ES File Explorer also cannot write anything on the SD Card on Redmi devices. Here's a video with solution. Following the steps worked for ES Explorer on my device. Can this be done programmatically?
As suggested by #CommonsWare here we have to use the new Storage Access Framework provided by android and will have to take permission from user to write SD card file as you said this is already written in the File Manager Application ES File Explorer.
Here is the code for Letting the user choose the "SD card" :
startActivityForResult(new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), requestCode);
which will look somewhat like this :
And get the Document path in pickedDirand pass further in your copyFile block
and use this path for writing the file :
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
if (resultCode != RESULT_OK)
return;
else {
Uri treeUri = resultData.getData();
DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
grantUriPermission(getPackageName(), treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
copyFile(sdCard.toString(), "/File.txt", path + "/new", pickedDir);
}
}
public void copyFile(String inputPath, String inputFile, String outputPath, DocumentFile pickedDir) {
InputStream in = null;
OutputStream out = null;
try {
//create output directory if it doesn't exist
File dir = new File(outputPath);
if (!dir.exists()) {
dir.mkdirs();
}
in = new FileInputStream(inputPath + inputFile);
//out = new FileOutputStream(outputPath + inputFile);
DocumentFile file = pickedDir.createFile("//MIME type", outputPath);
out = getContentResolver().openOutputStream(file.getUri());
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) {
/* I get the error here */
Log.e("tag", fnfe1.getMessage());
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
}
You need to add permission request run time in Android 6.0 (API Level 23) and up, here is the official docs
This is the code for WRITE_EXTERNAL_STORAGE
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG,"Permission is granted");
return true;
}
Ask for permission else like this
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
I have also got that problem but i solved by use the request the permission in run time and after forcefully give the permission.After the permission in App info of Android device. after declare the permission in manifest =>go to setting of your device => go to app info => go to permission =>
and finally allow the permission . just remember i just talking about after api level 22 means from marshmallow.
Its seems the runtime permission are implemented correctly but the issues seems from the device
If you are using Redmi than you have to manually allow the permission of specific app in Redmi security settings
This link shows how to enable permission in redmi security
After Android 4.3 on some devices, you can't get direct write access to FileSystem on SDcard.
You should use storage access framework for that.
I can see that you are copying the entire content of one file and trying to write the same to another file. I could suggest a better way to do this :
Assuming that you already checked for file existence
StringWriter temp=new StringWriter();
try{
FileInputStream fis=new FileInputStream(inputFile+inputPath);
int i;
while((i=fis.read())!=-1)
{
temp.write((char)i);
}
fis.close();
FileOutputStream fos = new FileOutputStream(outputPath, false); // true or false based on opening mode as appending or writing
fos.write(temp.toString(rs1).getBytes());
fos.close();
}
catch (Exception e){}
This code worked for my app...Let me know if this is working for you or not..
You can't copy or Delete files & Folder on external storage using third party app. like [file explorer].
It's data policy updated after KITKAT Version.
If only allow on system apps. So you can use an original file explorer (Come from ROM).
IF you need to use 3rd party app then ROOT your device. (Root permission is required)
I have a directory structure of files in external storage. They don't show up in the Android File Transfer app, so I think it's a media scanner problem.
I'm creating them with a FileOutputStream in a directory based on Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).
I have the following method, called from an activity, so context is an activity (forget that this blocks the main thread for now!):
public void scan(Context context, File base) {
File[] files = base.listFiles();
if (files == null) {
return;
} else {
for (File file : files) {
if (file.isFile()) {
String path = file.getAbsolutePath();
MediaScannerConnection.scanFile(context, new String[]{path}, null, null);
Log.e("Langstroth", path);
} else if (file.isDirectory()) {
this.scan(context, file);
}
}
}
}
public void scan(Context context) {
this.scan(context, this.baseDir);
}
}
The output of the log is as expected:
E/MyApp﹕ /storage/emulated/0/Documents/Langstroth/sample/5000/1430576404874.wav
E/MyApp﹕ /storage/emulated/0/Documents/Langstroth/sample/5000/1430577209491.wav
And then lots of:
E/MyApp﹕ Scan completed path /storage/emulated/0/Documents/Langstroth/sample/5000/1430576404874.wav uri content://media/external/audio/media/7836
E/MyApp﹕ Scan completed path /storage/emulated/0/Documents/Langstroth/sample/5000/1430577209491.wav uri content://media/external/audio/media/7838
This proves that the files exist. They don't show up in the Android File Transfer though.
Here's the strange thing. Another method:
public void otherDemo(Context context, File baseDir) {
String newPath = baseDir.getAbsolutePath() + "/some/random/dirs";
Log.e("Langstroth", "New path " + newPath);
File dir = new File(newPath);
dir.mkdirs();
Log.e("Langstroth", dir.exists() ? "Dir exists": "Dir does not exist");
File f = new File(dir, "myfile.txt");
try {
new BufferedOutputStream(new FileOutputStream(f)).close();
} catch (IOException e) {
e.printStackTrace();
}
Log.e("Langstroth", f.exists() ? "File exists": "File does not exist");
MediaScannerConnection.scanFile(context, new String[]{f.getAbsolutePath()}, null, null);
}
and the log output:
E/MyApp﹕ New path /storage/emulated/0/Documents/Langstroth/some/random/other/dirs
E/MyApp﹕ Dir exists
E/MyApp﹕ File exists
E/MyApp﹕ File: /storage/emulated/0/Documents/Langstroth/some/random/other/dirs/myfile.txt
E/MyApp﹕ Other scan completed path /storage/emulated/0/Documents/Langstroth/some/random/other/dirs/myfile.txt uri content://media/external/file/7842
One test file shows up, the others don't
Proof:
Where are the other files?
Generally speaking, before you let another process work with a file, you want to ensure all bytes are flushed to disk, via getFD().sync(). In particular, this seems to help with the whole media scanning thing.
the files shows up in a .listFiles(), and .exist(), and the callback for the MediaScanner says that it completed correctly. Surely an extant (if empty) file should show up?
The ways of the media scanner are mysterious. :-) IOW, beats me.
Bear in mind that there are multiple moving parts here: your app, the media scanner, the MTP daemon on Android, and your MTP client. The breakdown could be at any stage. If you unplug and re-plug in the device, and now the files show up in your MTP client, my guess would be that the MTP client is working off of a slightly stale cache.
I have a file on Internal Storage on the path e.g. /data/data/<package name>/folder/myfile
I don't have permissions to access this file but for my implementation I have to read this file. for this purpose I first run su command on the file and set permissions through chmod command to 777and then try to access the file. but still show that file does not exist. Please tell how can I can get this file to read.
Following is what I am trying to do.
public void runChmodAndSU(String filePath)
{
Process chperm;
try {
chperm = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(chperm.getOutputStream());
os.writeBytes("chmod 777 "+ filePath +"\n");
os.writeBytes("exit\n");
os.flush();
chperm.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
After running above code I check it this way:
File myFile = new File(filePath);
if (myFile.exists())
{
Log.e("Success!", "myFile Exists");
}
else {
Log.e("Failure!", "myFile Does not Exists");
}
Please tell me how can I read this very file. Is there any other way to access files you don't have permissions to?
You can't nor should you be allowed to access such files without the appropriate permissions set in AndroidManifest.xml for your application.
I can't tell if you were intending this to be a "hack android for me please?" question, or if you just don't know what android's uses-permission is about, but the way your question is worded, you really shouldn't be able to access the file.
If su is working, try chmod -R 777 /data/data/<package name>/
I have a problem with creating a folder and a file on the sdcard.
Here's the code:
File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/folder");
boolean success;
if (!folder.exists()) {
success = folder.mkdirs();
}
File obdt = new File(folder, "file.txt");
try {
success = obdt.createNewFile();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
With this code I expect to create the folderfolder in the Download folder of the sdcard and in this the file file. I want that the user can access the file. So I want to put it in a shared folder.
The success variable is true and when I run the code again the folder already exists and doesnt come in the if-block.
But I can't see the created folder and file on the sdcard in file explorer.
Info:getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() returns storage/sdcard/Download
I work with a Galaxy Nexus.
Damn! :)
Now I solved my problem...I was misunderstanding the operation of creating files in the file system.
When I spoke of file explorer I meant the file explorer of the operating system and NOT the file explorer in the DDMS :).
I thought when I create a file I will see it in the file explorer of the operating system but when the device is connected to the PC the files can only be seen in the DDMS file explorer.
Sorry I'm new to Android ;)
When the App is running standalone without PC connection and afterwards I connect with the PC I see the created files and folders of course :)
Thanks for help
Any errors from logcat?
Else: try something like Log.I("PATHNAME",folder.absolutePath()); and then look in your logcat to make sure where you are creating the folder where you think it is.
If you haven't done so already, you will need to give your app the correct permission to write to the SD Card by adding the line below to your Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
If you have already done that see if :
File obdt = new File(/sdcard/folder/file.txt)
try {
success = obdt.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
}
works.
You cannot see the folder/file in explorer? Maybe it is because the MediaScanner is active, but not adding your files. You can do this in your program or switch the Media Scanner of somewhere in your phone settings.
MediaScanner
Trigger MediaScanner
Try this out.
File dir = new File(Environment.getExternalStorageDirectory()
+ "/XXX/Wallpapers/");
File[] files = dir.listFiles();
if (files == null)
{
int numberOfImages = 0;
BitmapDrawable drawable = (BitmapDrawable) imageView
.getDrawable();
Bitmap bitmap = drawable.getBitmap();
File sdCardDirectory = Environment
.getExternalStorageDirectory();
new File(sdCardDirectory + "/XXX/Wallpapers/").mkdirs();
File image = new File(sdCardDirectory
+ "/XXX/Wallpapers/Sample" + numberOfImages + ".JPG");
boolean success = false;
FileOutputStream outStream;
try {
outStream = new FileOutputStream(image);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
success = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (success) {
Toast.makeText(
getApplicationContext(),
"Image saved successfully in Sdcard/XXX/Wallpapers",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),
"Error during image saving", Toast.LENGTH_LONG)
.show();
}
Dont forget to add permission in manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Apparently there is a known bug in MTP.
Issue 195362
All phones using MTP instead of USB Mass storage do not properly show the list of files when that phone is connected to a computer using a USB cable. Android apps running on the device also cannot see these files.
It is actually as old as 2012
I've encountered the same problem: created files and folders don't show immediately after being written to sdcard, despite the file being flushed and closed !!
They don't show on your computer over USB or a file explorer on the phone.
I observed three things:
if the absolute path of the file starts with /storage/emulated/0/ it doesn't mean it'll be on your sdcard - it could be on your main storage instead.
if you wait around 5 minutes, the files do begin to show over USB (i.e. Windows explorer and built-in file explorer)
if you use adb shell ls /sdcard from terminal, then the file does show! you could use adb pull ... to get the file immediately. You could probably use DDMS too.
Code I used was:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(myArrayList);
try {
File externalDir = getExternalStorageDirectory();
File newFile = new File(externalDir, "myfile.txt");
FileOutputStream os = new FileOutputStream(newFile);
os.write(json.getBytes());
os.flush();
os.close();
Timber.i("saved file to %s",newFile.getAbsoluteFile().toString());
}catch (Exception ex)
{
Toast.makeText(getApplicationContext(), "Save to private external storage failed. Error message is " + ex.getMessage(), Toast.LENGTH_LONG).show();
}
and
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(myArrayList);
try {
File externalDir = getExternalStorageDirectory();
File newFile = new File(externalDir, "myfile.txt");
FileWriter fw = new FileWriter(newFile);
fw.write(json);
fw.flush();
fw.close();
Timber.i("saved file to %s",newFile.getAbsoluteFile().toString());
}catch (Exception ex)
{
Toast.makeText(getApplicationContext(), "Save to private external storage failed. Error message is " + ex.getMessage(), Toast.LENGTH_LONG).show();
}
why is it like this? Seems like another one of those "Android-isms" that you have to suffer through the first time you experience it.
I have error in line:
workbook.write();
When I try debug, i see massage: "Source not found."
How it fix?
private void exportExcel() throws IOException, WriteException{
File file = new File(Environment.getExternalStorageDirectory() + "/backup.xls");
WritableWorkbook workbook = Workbook.createWorkbook(file);
workbook.createSheet("worksheet", 0);
workbook.write();
workbook.close();
}
Thanks in advance
WTF my code above begin to work!!!
When I started, I using default jexcelapi. Afterwards I begin using alternative jexcelapi, but it also not work.
When I try your code with little changes - it work! Your code:
private void exportExcel() throws WriteException, IOException{
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard + "/myFolder");
//make them in case they're not there
dir.mkdirs();
//create a standard java.io.File object for the Workbook to use
File wbfile = new File(dir, "backup.xls");
WritableWorkbook workbook = null;
try{
workbook = Workbook.createWorkbook(wbfile);
workbook.createSheet("worksheet", 0);
workbook.write();
workbook.close();
} catch (IOException ex) {
Log.e("Workbook Test", "Could not create " + wbfile.getPath(), ex);
}
}
But when I try my code above, it also work.
Maybe Eclipse not instantly update using library?
Thank you very much!
P.S. Excuse me for my bad english.
Your code does not check that the external storage directory is actually available. You need to call getExternalStorageState and check the return value against the various MEDIA_* values defined in Environment. If the directory is not available, that may cause the problem.
The problem also may be that you are trying to write to the root of the external storage directory. From the docs:
Applications should not directly use this top-level directory, in order to avoid polluting the user's root namespace. Any files that are private to the application should be placed in a directory returned by Context.getExternalFilesDir, which the system will take care of deleting if the application is uninstalled.
EDIT
Try this code:
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard + "/myFolder");
//make them in case they're not there
dir.mkdirs();
//create a standard java.io.File object for the Workbook to use
File wbfile = new File(dir, "backup.xls");
try{
WritableWorkbook workbook = Workbook.createWorkbook(wbfile);
workbook.createSheet("worksheet", 0);
workbook.write();
workbook.close();
} catch (IOException ex) {
Log.e("Workbook Test", "Could not create " + wbfile.getPath(), ex);
}
return wb;
That should tell you more about what's going on.
EDIT 2
After a little more research, I found another possible issue: JExcelApi uses a lot of resources when it is creating a file. One solution is to use a temp file. Add the following code:
WorkbookSettings wbSettings = new WorkbookSettings();
wbSettings.setUseTemporaryFileDuringWrite(true);
and inside the try block, change the line that creates the workbook:
WritableWorkbook workbook = Workbook.createWorkbook(wbfile, wbSettings);