I am working on filling a pdf form and save it into the device but the first catch returns this: "FileNotFoundException: /storage/emulated/0/myFile.pdf: open failed: EPERM (Operation not permitted)". Even though I added a checkPermission function to my code.
This is my code :
checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, 101);
checkPermission(Manifest.permission.READ_EXTERNAL_STORAGE, 101);
File file = new File(Environment.getExternalStorageDirectory().getPath()+ "/myFile.pdf");
try {
PdfReader reader = new PdfReader(getResources().openRawResource(R.raw.bail_1));
try {
PdfWriter writer = new PdfWriter(new FileOutputStream(file));
PdfDocument pdf = new PdfDocument(reader, writer);
pdf.close();
writer.close();
Toast.makeText(this, "OK", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(this,"FileNotFoundException: " + e.getMessage(), Toast.LENGTH_SHORT).show;
return;
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this,"FileNotFoundException: " + e.getMessage(), Toast.LENGTH_SHORT).show;
return;
}
private void checkPermission(String permission, int requestCode) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{permission}, requestCode);
}
}
this is not just regarding the reader issue
it may be about the path.....change your code to this and check
// change your path receiving line to
File file = new File(getFilePath("myFile.pdf"));
//and Path getting Function
private String getFilePath(String pdfName) {
ContextWrapper contextWrapper = new
ContextWrapper(getApplicationContext());
File fileDir = Environment.getExternalStorageDirectory();
File pdfFile = new File (fileDir, pdfName);
return pdfFile.getPath();
}
//Old Conventional ways do not work in some cases
Related
I am trying to copy a file over to the root SD card on an Android device.
When I execute the code, it is going to the sdcard/Android/Data/<packageName>/files folder.
I have tried several different options without any success.
Also, I have checked the app to make sure it has write and read access to external memory.
private void copyfiles() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("ini");
} catch (IOException e) {
Log.e("tag", "Failed to get asset file list.", e);
}
if (files != null)
for (String filename: files) {
InputStream in = null;
OutputStream out = null;
try { in = assetManager.open("sdcard/" + filename);
//File outFile = new File(Environment.getExternalStorageDirectory(), filename);
File outFile = new File(getExternalFilesDir(null), filename);
if (!(outFile.exists())) { // File does not exist...
out = new FileOutputStream(outFile);
pastefiles( in , out);
}
} catch (IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
} finally {
if ( in != null) {
try { in .close();
} catch (IOException e) {
// NOOP
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
// NOOP
}
}
}
}
}
I am creating Xmpp application using SMACK api and Spark for test.
I am able to send from Spark but I cannot see Any Directory and File created in android gallery.
I log the method incoming.getAmountWritten() and it is giving me
07-27 21:00:58.789: V/Receiving Status ...(17652): 208861
It means I have got the file and now I have to write on physical storage. May be there is problem with my android code.
Please find Android Code
#Override
public void fileTransferRequest(final FileTransferRequest fileRequest) {
final File dir = Environment.getExternalStorageDirectory();
final File folder = new File(dir+ "/illuxplain/");
boolean success = true;
if (!folder.exists()) {
success = folder.mkdir();
}
if (success) {
Thread receiving = new Thread(new Runnable() {
#Override
public void run() {
IncomingFileTransfer incoming = fileRequest.accept();
Log.v("Receiving File Name", incoming.getFileName());
File file = new File(folder, incoming.getFileName());
try {
incoming.recieveFile(file);
while (!incoming.isDone()) {
try {
Thread.sleep(1000L);
} catch (Exception e) {
Log.e("", e.getMessage());
}
if (incoming.getStatus().equals(Status.error)) {
Log.e("ERROR!!! ", incoming.getError() + "");
}
if (incoming.getException() != null) {
incoming.getException().printStackTrace();
}
}
Log.v("Receiving Status ... ",""+incoming.getAmountWritten());
} catch (Exception e) {
e.printStackTrace();
Log.e("", e.getMessage());
}
}
});
receiving.start();
}else{
System.out.println("Directory Not Created");
}
}
}
When I go to gallery and see if I got the file. I see no directory created and of course no file.
You need to write the data into the file. Here is an example to code to write the data in to the file
File file = new File(folder, incoming.getFileName());
String string = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = new FileOutputStream(file);
outputStream.write(string.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
Could someone look at this snippet of code please and let me know what I'm doing wrong? It's a simple function that takes a string as parameter which it uses as a file name, adding ".txt" to the end of it.
The function checks if the file exists, creating it if it doesn't and then writes two lines of text to the file. Everything appears to be working and the file is created successfully on the sd card. However, after everything is done, the file is empty (and has a size of 0 bytes).
I suspect it's something obvious that I'm overlooking.
public void writeFile(String fileName) {
String myPath = new File(Environment.getExternalStorageDirectory(), "SubFolderName");
myPath.mkdirs();
File file = new File(myPath, fileName+".txt");
try {
if (!file.exists()) {
if (!file.createNewFile()) {
Toast.makeText(this, "Error Creating File", Toast.LENGTH_LONG).show();
return;
}
}
OutputStreamWriter writer = new OutputStreamWriter(openFileOutput(file.getName(), Context.MODE_PRIVATE));
writer.append("First line").append('\n');
writer.append("Second line").append('\n');
writer.close();
}
catch (IOException e) {
// Do whatever
}
}
Hi I will show you the full code I use, works perfect.
I don't use
new OutputStreamWriter()
i use
new BufferedWriter()
here is my Snippet
public void writeToFile(Context context, String fileName, String data) {
Writer mwriter;
File root = Environment.getExternalStorageDirectory();
File dir = new File(root.getAbsolutePath() + File.separator + "myFolder");
if (!dir.isDirectory()) {
dir.mkdir();
}
try {
if (!dir.isDirectory()) {
throw new IOException(
"Unable to create directory myFolder. SD card mounted?");
}
File outputFile = new File(dir, fileName);
mwriter = new BufferedWriter(new FileWriter(outputFile));
mwriter.write(data); // DATA WRITE TO FILE
Toast.makeText(context.getApplicationContext(),
"successfully saved to: " + outputFile.getAbsolutePath(), Toast.LENGTH_LONG).show();
mwriter.close();
} catch (IOException e) {
Log.w("write log", e.getMessage(), e);
Toast.makeText(context, e.getMessage() + " Unable to write to external storage.",Toast.LENGTH_LONG).show();
}
}
-- Original Code --
That one took a while to find out. The javadocs
here brought me on the right track.
It says:
Parameters
name The name of the file to open; can not contain path separators.
mode Operating mode. Use 0 or MODE_PRIVATE for the default operation, MODE_APPEND to append to an existing file, MODE_WORLD_READABLE and MODE_WORLD_WRITEABLE to control permissions.
The file is created, if it does not exist, but it is created in the private app space. You create the file somewhere on the sd card using File.createNewFile() but when you do context.openFileOutput() it creates always a private file in the private App space.
EDIT: Here's my code. I've expanded your method by writing and reading the lines and print what I got to logcat.
<pre>
public void writeFile(String fileName) {
try {
OutputStreamWriter writer = new OutputStreamWriter(
getContext().openFileOutput(fileName + ".txt", Context.MODE_PRIVATE));
writer.append("First line").append('\n');
writer.append("Second line").append('\n');
writer.close();
}
catch (IOException e) {
Log.e("STACKOVERFLOW", e.getMessage(), e);
return;
// Do whatever
}
// Now read the file
try {
BufferedReader is = new BufferedReader(
new InputStreamReader(
getContext().openFileInput(fileName + ".txt")));
for(String line = is.readLine(); line != null; line = is.readLine())
Log.d("STACKOVERFLOW", line);
is.close();
} catch (IOException e) {
Log.e("STACKOVERFLOW", e.getMessage(), e);
return;
// Do whatever
}
}
Change the mode from Context.MODE_PRIVATE to Context.MODE_APPEND in openFileOutput()
MODE_APPEND
MODE_PRIVATE
Instead of
OutputStreamWriter writer = new OutputStreamWriter(openFileOutput(file.getName(), Context.MODE_PRIVATE));
Use
OutputStreamWriter writer = new OutputStreamWriter(openFileOutput(file.getName(), Context.MODE_APPEND));
UPDATE :
1.
FileOutputStream osr = new FileOutputStream(file.getName(), true); // this will set append flag to true
OutputStreamWriter writer = new OutputStreamWriter(osr);
BufferedWriter fbw = new BufferedWriter(writer);
fbw.write("First line");
fbw.newLine();
fbw.write("Second line");
fbw.newLine();
fbw.close();
Or 2.
private void writeFileToInternalStorage() {
FileOutputStream osr = new FileOutputStream(file.getName(), true); // this will set append flag to true
String eol = System.getProperty("line.separator");
BufferedWriter fbw = null;
try {
OutputStreamWriter writer = new OutputStreamWriter(osr);
fbw = new BufferedWriter(writer);
fbw.write("First line" + eol);
fbw.write("Second line" + eol);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fbw != null) {
try {
fbw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
In my Android app I should store the data from user in simple text-file, that I created in the raw directory. After this, I'm trying to write file in APPEND MODE by using simple code from the Google's examples:
try
{
FileOutputStream fos = openFileOutput(FILE_NAME, Context.MODE_APPEND);
fos.write((nameArticle+"|"+indexArticle).getBytes());
fos.close();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
But nothing happens: no exceptions, but I can see nothing in my FILE_NAME, besides the single record, which was added by me.
What am I doing wrong ? Is it possible at common to write to file in emulator ?
openFileOutput will only allow you to open a private file associated with this Context's application package for writing. I'm not sure where the file you're trying to write to is located. I mean full path. You can use the code below to write to a file located anywhere (as long as you have perms). The example is using the external storage, but you should be able to modify it to write anywhere:
public Uri writeToExternalStoragePublic() {
final String filename = mToolbar.GetTitle() + ".html";
final String packageName = this.getPackageName();
final String folderpath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + packageName + "/files/";
File folder = new File(folderpath);
File file = null;
FileOutputStream fOut = null;
try {
try {
if (folder != null) {
boolean exists = folder.exists();
if (!exists)
folder.mkdirs();
file = new File(folder.toString(), filename);
if (file != null) {
fOut = new FileOutputStream(file, false);
if (fOut != null) {
fOut.write(mCurrentReportHtml.getBytes());
}
}
}
} catch (IOException e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
}
return Uri.fromFile(file);
} finally {
if (fOut != null) {
try {
fOut.flush();
fOut.close();
} catch (IOException e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
}
In the example you have given, try catching 'I0Exception`, I have a feeling you do not have permission where you are trying to write.
Have a Happy New Year.
I want to create a file in external storage sdCard and write to it.I have searched through internet and try but not getting the result,I have added permission in Android Manifest file as well,I am doing this on Emulator,I am trying the following code and getting a ERRR", "Could not create file".
btnWriteSDFile = (Button) findViewById(R.id.btnWriteSDFile);
btnWriteSDFile.setOnClickListener(new OnClickListener() {
//private Throwable e;
#Override
public void onClick(View v) {
// write on SD card file data from the text box
try {
File myFile = new File("/sdcard/mysdfile.txt");
myFile.createNewFile();
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
myOutWriter.append(txtData.getText());
myOutWriter.close();
fOut.close();
} catch (Exception e) {
Log.e("ERRR", "Could not create file",e);
}
}// onClick
}); // btnWriteSDFile
You can do this with this code also.
public class WriteSDCard extends Activity {
private static final String TAG = "MEDIA";
private TextView tv;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.TextView01);
checkExternalMedia();
writeToSDFile();
readRaw();
}
/** Method to check whether external media available and writable. This is adapted from
http://developer.android.com/guide/topics/data/data-storage.html#filesExternal */
private void checkExternalMedia(){
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// Can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// Can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Can't read or write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
tv.append("\n\nExternal Media: readable="
+mExternalStorageAvailable+" writable="+mExternalStorageWriteable);
}
/** Method to write ascii text characters to file on SD card. Note that you must add a
WRITE_EXTERNAL_STORAGE permission to the manifest file or this method will throw
a FileNotFound Exception because you won't have write permission. */
private void writeToSDFile(){
// Find the root of the external storage.
// See http://developer.android.com/guide/topics/data/data- storage.html#filesExternal
File root = android.os.Environment.getExternalStorageDirectory();
tv.append("\nExternal file system root: "+root);
// See http://stackoverflow.com/questions/3551821/android-write-to-sd-card-folder
File dir = new File (root.getAbsolutePath() + "/download");
dir.mkdirs();
File file = new File(dir, "myData.txt");
try {
FileOutputStream f = new FileOutputStream(file);
PrintWriter pw = new PrintWriter(f);
pw.println("Hi , How are you");
pw.println("Hello");
pw.flush();
pw.close();
f.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.i(TAG, "******* File not found. Did you" +
" add a WRITE_EXTERNAL_STORAGE permission to the manifest?");
} catch (IOException e) {
e.printStackTrace();
}
tv.append("\n\nFile written to "+file);
}
/** Method to read in a text file placed in the res/raw directory of the application. The
method reads in all lines of the file sequentially. */
private void readRaw(){
tv.append("\nData read from res/raw/textfile.txt:");
InputStream is = this.getResources().openRawResource(R.raw.textfile);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr, 8192); // 2nd arg is buffer size
// More efficient (less readable) implementation of above is the composite expression
/*BufferedReader br = new BufferedReader(new InputStreamReader(
this.getResources().openRawResource(R.raw.textfile)), 8192);*/
try {
String test;
while (true){
test = br.readLine();
// readLine() returns null if no more lines in the file
if(test == null) break;
tv.append("\n"+" "+test);
}
isr.close();
is.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
tv.append("\n\nThat is all");
}
}
To write into external storage in Lollipop+ devices we need:
Add the following permission into Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Request an approval from the user:
public static final int REQUEST_WRITE_STORAGE = 112;
private requestPermission(Activity context) {
boolean hasPermission = (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermission) {
ActivityCompat.requestPermissions(context,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_WRITE_STORAGE);
} else {
// You are allowed to write external storage:
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/new_folder";
File storageDir = new File(path);
if (!storageDir.exists() && !storageDir.mkdirs()) {
// This should never happen - log handled exception!
}
}
Handle the user response inside Activity:
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
{
case Preferences.REQUEST_WRITE_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "The app was allowed to write to your storage!", Toast.LENGTH_LONG).show();
// Reload the activity with permission granted or use the features what required the permission
} else {
Toast.makeText(this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
}
Even though above answers are correct, I wanna add a notice to distinguish types of storage:
Internal storage: It should say 'private storage' because it belongs to the app and cannot be shared. Where it's saved is based on where the app installed. If the app was installed on an SD card (I mean the external storage card you put more into a cell phone for more space to store images, videos, ...), your file will belong to the app means your file will be in an SD card. And if the app was installed on an Internal card (I mean the onboard storage card coming with your cell phone), your file will be in an Internal card.
External storage: It should say 'public storage' because it can be shared. And this mode divides into 2 groups: private external storage and public external storage. Basically, they are nearly the same, you can consult more from this site: https://developer.android.com/training/data-storage/files
A real SD card (I mean the external storage card you put more into a cell phone for more space to store images, videos, ...): this was not stated clearly on Android docs, so many people might be confused with how to save files in this card.
Here is the link to source code for cases I mentioned above: https://github.com/mttdat/utils/blob/master/utils/src/main/java/mttdat/utils/FileUtils.java
The code below creates a Documents directory and then a sub-directory for the application and saved the files to it.
public class loadDataTooDisk extends AsyncTask<String, Integer, String> {
String sdCardFileTxt;
#Override
protected String doInBackground(String... params)
{
//check to see if external storage is avalibel
checkState();
if(canW == canR == true)
{
//get the path to sdcard
File pathToExternalStorage = Environment.getExternalStorageDirectory();
//to this path add a new directory path and create new App dir (InstroList) in /documents Dir
File appDirectory = new File(pathToExternalStorage.getAbsolutePath() + "/documents/InstroList");
// have the object build the directory structure, if needed.
appDirectory.mkdirs();
//test to see if it is a Text file
if ( myNewFileName.endsWith(".txt") )
{
//Create a File for the output file data
File saveFilePath = new File (appDirectory, myNewFileName);
//Adds the textbox data to the file
try{
String newline = "\r\n";
FileOutputStream fos = new FileOutputStream (saveFilePath);
OutputStreamWriter OutDataWriter = new OutputStreamWriter(fos);
OutDataWriter.write(equipNo.getText() + newline);
// OutDataWriter.append(equipNo.getText() + newline);
OutDataWriter.append(equip_Type.getText() + newline);
OutDataWriter.append(equip_Make.getText()+ newline);
OutDataWriter.append(equipModel_No.getText()+ newline);
OutDataWriter.append(equip_Password.getText()+ newline);
OutDataWriter.append(equipWeb_Site.getText()+ newline);
//OutDataWriter.append(equipNotes.getText());
OutDataWriter.close();
fos.flush();
fos.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
return null;
}
}
This one builds the file name
private String BuildNewFileName()
{ // creates a new filr name
Time today = new Time(Time.getCurrentTimezone());
today.setToNow();
StringBuilder sb = new StringBuilder();
sb.append(today.year + ""); // Year)
sb.append("_");
sb.append(today.monthDay + ""); // Day of the month (1-31)
sb.append("_");
sb.append(today.month + ""); // Month (0-11))
sb.append("_");
sb.append(today.format("%k:%M:%S")); // Current time
sb.append(".txt"); //Completed file name
myNewFileName = sb.toString();
//Replace (:) with (_)
myNewFileName = myNewFileName.replaceAll(":", "_");
return myNewFileName;
}
Hope this helps! It took me a long time to get it working.
You should read the documentation on storing stuff externally on Android. There's a multitude of problems that could exist with your current code, and I think going over the documentation might help you iron them out.
Supplemental Answer
After writing to external storage, some file managers don't see the file right away. This can be confusing if a user thinks they copied something to the SD card, but then can't find it there. So after you copy the file, run the following code to notify file managers of its presence.
MediaScannerConnection.scanFile(
context,
new String[]{myFile.getAbsolutePath()},
null,
null);
See the documentation and this answer for more.
You can find these method usefull in reading and writing data in android.
public void saveData(View view) {
String text = "This is the text in the file, this is the part of the issue of the name and also called the name od the college ";
FileOutputStream fos = null;
try {
fos = openFileOutput("FILE_NAME", MODE_PRIVATE);
fos.write(text.getBytes());
Toast.makeText(this, "Data is saved "+ getFilesDir(), Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fos!= null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void logData(View view) {
FileInputStream fis = null;
try {
fis = openFileInput("FILE_NAME");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb= new StringBuilder();
String text;
while((text = br.readLine()) != null){
sb.append(text).append("\n");
Log.e("TAG", text
);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ContextWrapper contextWrapper = new ContextWrapper(getApplicationContext()); //getappcontext for just this activity context get
File file = contextWrapper.getDir(file_path, Context.MODE_PRIVATE);
if (!isExternalStorageAvailable() || isExternalStorageReadOnly())
{
saveToExternalStorage.setEnabled(false);
}
else
{
External_File = new File(getExternalFilesDir(file_path), file_name);//if ready then create a file for external
}
}
try
{
FileInputStream fis = new FileInputStream(External_File);
DataInputStream in = new DataInputStream(fis);
BufferedReader br =new BufferedReader(new InputStreamReader(in));
String strLine;
while ((strLine = br.readLine()) != null)
{
myData = myData + strLine;
}
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
InputText.setText("Save data of External file:::: "+myData);
private static boolean isExternalStorageReadOnly()
{
String extStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState))
{
return true;
}
return false;
}
private static boolean isExternalStorageAvailable()
{
String extStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(extStorageState))
{
return true;
}
return false;
}