16 | * This class will create a directory having same name as your 17 | * application. With all the states handled and reported back to 18 | * developer. 19 | *
20 | */ 21 | public class AppExternalFileWriter { 22 | 23 | private static final String canNotWriteFile = "Can not write file: "; 24 | private static final String canNotCreateDirectory = "Can not create directory: "; 25 | private final File externalStorageDirectory; 26 | private final File externalCacheDirectory; 27 | private Context context; 28 | private File appDirectory; 29 | private File appCacheDirectory; 30 | 31 | /** 32 | * Creates external file writer 33 | * 34 | * @param context 35 | * : Context 36 | */ 37 | public AppExternalFileWriter(Context context) { 38 | this.context = context; 39 | externalStorageDirectory = Environment.getExternalStorageDirectory(); 40 | externalCacheDirectory = context.getExternalCacheDir(); 41 | } 42 | 43 | private File createFile(String fileName, boolean inCache) throws ExternalFileWriterException { 44 | return createFile(fileName, getAppDirectory(inCache)); 45 | } 46 | 47 | /** 48 | * Create a file in the app directory with given file name. 49 | * 50 | * @param fileName 51 | * : Desired name of the file 52 | * @param parent 53 | * parent of the file 54 | * 55 | * @return : File with desired name 56 | */ 57 | private File createFile(String fileName, File parent) throws ExternalFileWriterException { 58 | if (isExternalStorageAvailable(true)) { 59 | try { 60 | 61 | if (parent.isDirectory()) { 62 | 63 | File detailFile = new File(parent, fileName); 64 | if (!detailFile.exists()) 65 | detailFile.createNewFile(); 66 | else { 67 | String messege = "File already there "; 68 | throwException(messege); 69 | } 70 | return detailFile; 71 | } else { 72 | throwException(parent + " should be a directory"); 73 | } 74 | } catch (IOException e) { 75 | e.printStackTrace(); 76 | String errorMessege = "IOException " + e; 77 | throwException(errorMessege); 78 | } catch (Exception e) { 79 | e.printStackTrace(); 80 | String errorMessege = "Exception " + e; 81 | throwException(errorMessege); 82 | } 83 | } 84 | return null; 85 | } 86 | 87 | /** Creates app directory */ 88 | private void createAppDirectory() throws ExternalFileWriterException { 89 | String directoryName = context.getString(context.getApplicationInfo().labelRes); 90 | 91 | if (isExternalStorageAvailable(false)) { 92 | 93 | appDirectory = new File(Environment.getExternalStorageDirectory().toString(), 94 | directoryName); 95 | createDirectory(appDirectory); 96 | 97 | appCacheDirectory = new File(externalCacheDirectory, directoryName); 98 | createDirectory(appCacheDirectory); 99 | 100 | } 101 | 102 | } 103 | 104 | private double getAvailableSpace() { 105 | StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath()); 106 | double sdAvailSize = (double) stat.getAvailableBlocks() * (double) stat.getBlockSize(); 107 | return sdAvailSize; 108 | } 109 | 110 | private boolean isExternalStorageAvailable(boolean isForFile) 111 | throws ExternalFileWriterException { 112 | String errorStarter = (isForFile) ? canNotWriteFile : canNotCreateDirectory; 113 | 114 | String storageState = Environment.getExternalStorageState(); 115 | 116 | if (storageState.equals(Environment.MEDIA_MOUNTED)) { 117 | return true; 118 | } else if (storageState.equals(Environment.MEDIA_BAD_REMOVAL)) { 119 | throwException(errorStarter + "Media was removed before it was unmounted."); 120 | } else if (storageState.equals(Environment.MEDIA_CHECKING)) { 121 | throwException(errorStarter + "Media is present and being disk-checked, " 122 | + "Please wait and try after some time"); 123 | } else if (storageState.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) { 124 | throwException(errorStarter + "Presented Media is read only"); 125 | } else if (storageState.equals(Environment.MEDIA_NOFS)) { 126 | throwException(errorStarter + "Blank or unsupported file media"); 127 | } else if (storageState.equals(Environment.MEDIA_SHARED)) { 128 | throwException(errorStarter + "Media is shared with USB mass storage"); 129 | } else if (storageState.equals(Environment.MEDIA_REMOVED)) { 130 | throwException(errorStarter + "Media is not present"); 131 | } else if (storageState.equals(Environment.MEDIA_UNMOUNTABLE)) { 132 | throwException(errorStarter + "Media is present but cannot be mounted"); 133 | } else if (storageState.equals(Environment.MEDIA_UNMOUNTED)) { 134 | throwException(errorStarter + "Media is present but not mounted"); 135 | } 136 | 137 | return false; 138 | } 139 | 140 | private void throwException(String errorMessege) throws ExternalFileWriterException { 141 | throw new ExternalFileWriterException(errorMessege); 142 | } 143 | 144 | private File createDirectory(File directory) throws ExternalFileWriterException { 145 | if (!directory.exists() || !directory.isDirectory()) { 146 | if (directory.mkdirs()) { 147 | String messege = "directory " + directory + " created : Path " 148 | + directory.getPath(); 149 | 150 | } else { 151 | if (directory.exists()) { 152 | if (directory.isDirectory()) { 153 | String messege = "directory " + directory + " Already exists : Path " 154 | + directory.getPath(); 155 | 156 | } else { 157 | String messege = directory 158 | + "should be a directory but found a file : Path " 159 | + directory.getPath(); 160 | throwException(messege); 161 | } 162 | 163 | } 164 | } 165 | } 166 | return directory; 167 | } 168 | 169 | /** 170 | * Write byte array to file. Will show error if given file is a directory. 171 | * 172 | * @param file 173 | * : File where data is to be written. 174 | * @param data 175 | * String which you want to write a file. If size of this is 176 | * greater than size available, it will show error. 177 | */ 178 | private void writeDataToFile(File file, String data) throws ExternalFileWriterException { 179 | byte[] stringBuffer = data.getBytes(); 180 | writeDataToFile(file, stringBuffer); 181 | } 182 | 183 | /** 184 | * Write byte array to file. Will show error if given file is a directory. 185 | * 186 | * @param file 187 | * : File where data is to be written. 188 | * @param data 189 | * byte array which you want to write a file. If size of this is 190 | * greater than size available, it will show error. 191 | */ 192 | private void writeDataToFile(File file, byte[] data) throws ExternalFileWriterException { 193 | if (isExternalStorageAvailable(true)) { 194 | if (file.isDirectory()) { 195 | throwException(file + " is not a file, can not write data in it"); 196 | } else { 197 | if (file != null && data != null) { 198 | double dataSize = data.length; 199 | double remainingSize = getAvailableSpace(); 200 | if (dataSize >= remainingSize) { 201 | throwException("Not enough size available"); 202 | 203 | } else { 204 | try { 205 | FileOutputStream out = new FileOutputStream(file); 206 | out.write(data); 207 | out.close(); 208 | } catch (IOException e) { 209 | e.printStackTrace(); 210 | } catch (Exception e) { 211 | e.printStackTrace(); 212 | } 213 | } 214 | } 215 | 216 | } 217 | } 218 | } 219 | 220 | private File getAppDirectory(boolean inCache) { 221 | return (inCache) ? this.appCacheDirectory : this.appDirectory; 222 | } 223 | 224 | /** 225 | * Creates subdirectory in application directory 226 | * 227 | * @param directoryName 228 | * name of subdirectory 229 | * 230 | * @return File object of created subdirectory 231 | * 232 | * @throws ExternalFileWriterException 233 | * if external storage is not available 234 | */ 235 | public File createSubDirectory(String directoryName, boolean inCache) 236 | throws ExternalFileWriterException { 237 | if (isExternalStorageAvailable(false)) { 238 | 239 | getAppDirectory(); 240 | 241 | File subDirectory = new File(getAppDirectory(inCache), directoryName); 242 | 243 | return createDirectory(subDirectory); 244 | } else 245 | return null; 246 | } 247 | 248 | /** 249 | * Checks whether directory with given name exists in AppDirectory 250 | * 251 | * @param directoryName 252 | * : Name of the directory to check. 253 | * 254 | * @return true if a directory with "directoryName" exists, false otherwise 255 | */ 256 | public boolean isDirectoryExists(String directoryName, boolean checkInCache) { 257 | File parentDirectory = (checkInCache) ? appCacheDirectory : appDirectory; 258 | return isDirectoryExists(directoryName, parentDirectory); 259 | } 260 | 261 | /** 262 | * Check whether file with given name exists in parentDirectory or not. 263 | * 264 | * @param fileName 265 | * : Name of the file to check. 266 | * @param parentDirectory 267 | * : Parent directory where directory with "fileName" should be present 268 | * 269 | * @return true if a file with "fileName" exists, false otherwise 270 | */ 271 | public boolean isFileExists(String fileName, File parentDirectory) { 272 | File directoryToCheck = new File(parentDirectory, fileName); 273 | return directoryToCheck.exists() && directoryToCheck.isFile(); 274 | } 275 | 276 | /** 277 | * Checks whether file with given name exists in AppDirectory 278 | * 279 | * @param fileName 280 | * : Name of the file to check. 281 | * 282 | * @return true if a file with "directoryName" exists, false otherwise 283 | */ 284 | public boolean isFileExists(String fileName, boolean checkInCache) { 285 | File parentDirectory = (checkInCache) ? appCacheDirectory : appDirectory; 286 | return isFileExists(fileName, parentDirectory); 287 | } 288 | 289 | /** 290 | * Check whether directory with given name exists in parentDirectory or not. 291 | * 292 | * @param directoryName 293 | * : Name of the directory to check. 294 | * @param parentDirectory 295 | * : Parent directory where directory with "directoryName" should be present 296 | * 297 | * @return true if a directory with "directoryName" exists, false otherwise 298 | */ 299 | public boolean isDirectoryExists(String directoryName, File parentDirectory) { 300 | File directoryToCheck = new File(parentDirectory, directoryName); 301 | return directoryToCheck.exists() && directoryToCheck.isDirectory(); 302 | } 303 | 304 | /** 305 | * Creates subdirectory in parent directory 306 | * 307 | * @param parent 308 | * : Parent directory where directory with "directoryName" should be created 309 | * @param directoryName 310 | * name of subdirectory 311 | * 312 | * @return File object of created subdirectory 313 | * 314 | * @throws ExternalFileWriterException 315 | * if external storage is not available 316 | */ 317 | public File createSubDirectory(File parent, String directoryName) 318 | throws ExternalFileWriterException { 319 | if (isExternalStorageAvailable(false)) { 320 | 321 | getAppDirectory(); 322 | 323 | if (!parent.isDirectory()) 324 | throwException(parent.getName() + " Must be a directory "); 325 | 326 | File subDirectory = new File(parent, directoryName); 327 | 328 | return createDirectory(subDirectory); 329 | } else 330 | return null; 331 | } 332 | 333 | /** 334 | * Deletes given directory with all its subdirectories and its files. 335 | * 336 | * @param directory 337 | * : Directory to delete 338 | */ 339 | public void deleteDirectory(File directory) { 340 | if (directory != null) { 341 | if (directory.isDirectory()) 342 | for (File child : directory.listFiles()) { 343 | 344 | if (child != null) { 345 | if (child.isDirectory()) 346 | deleteDirectory(child); 347 | else 348 | child.delete(); 349 | } 350 | } 351 | 352 | directory.delete(); 353 | } 354 | // return false; 355 | } 356 | 357 | /** 358 | * Get created app directory 359 | * 360 | * @return File object of created AppDirectory 361 | */ 362 | public File getAppDirectory() throws ExternalFileWriterException { 363 | if (appDirectory == null) { 364 | createAppDirectory(); 365 | } 366 | return appDirectory; 367 | } 368 | 369 | /** 370 | * get External Cache directory 371 | * 372 | * @return File object of External Cache directory 373 | */ 374 | public File getExternalCacheDirectory() { 375 | return externalCacheDirectory; 376 | } 377 | 378 | /** 379 | * Get external storage directory 380 | * 381 | * @return File object of external storage directory 382 | */ 383 | public File getExternalStorageDirectory() { 384 | return externalStorageDirectory; 385 | } 386 | 387 | /** 388 | * Write data in file of a parent directory 389 | * 390 | * @param parent 391 | * parent directory 392 | * @param fileName 393 | * desired filename 394 | * @param data 395 | * data 396 | * 397 | * @throws ExternalFileWriterException 398 | * if external storage is not available or free space is 399 | * less than size of the data 400 | */ 401 | public void writeDataToFile(File parent, String fileName, byte[] data) 402 | throws ExternalFileWriterException { 403 | if (isExternalStorageAvailable(true)) { 404 | getAppDirectory(); 405 | 406 | File file = createFile(fileName, parent); 407 | 408 | writeDataToFile(file, data); 409 | } 410 | } 411 | 412 | /** 413 | * Writes data to the file. The file will be created in the directory name 414 | * same as app. 415 | * 416 | * @param fileName 417 | * name of the file 418 | * @param data 419 | * data to write 420 | * 421 | * @throws ExternalFileWriterException 422 | * if external storage is not available or free space is 423 | * less than size of the data 424 | */ 425 | public void writeDataToFile(String fileName, String data, boolean inCache) 426 | throws ExternalFileWriterException { 427 | if (isExternalStorageAvailable(true)) { 428 | getAppDirectory(); 429 | 430 | File file = createFile(fileName, inCache); 431 | 432 | writeDataToFile(file, data); 433 | } 434 | } 435 | 436 | /** 437 | * Writes data to the file. The file will be created in the directory name 438 | * same as app. 439 | * 440 | * @param fileName 441 | * name of the file 442 | * @param data 443 | * data to write 444 | * 445 | * @throws ExternalFileWriterException 446 | * if external storage is not available or free space is 447 | * less than size of the data 448 | */ 449 | public void writeDataToFile(String fileName, byte[] data, boolean inCache) 450 | throws ExternalFileWriterException { 451 | if (isExternalStorageAvailable(true)) { 452 | getAppDirectory(); 453 | 454 | File file = createFile(fileName, inCache); 455 | 456 | writeDataToFile(file, data); 457 | } 458 | } 459 | 460 | /** 461 | * Write data in file of a parent directory 462 | * 463 | * @param parent 464 | * parent directory 465 | * @param fileName 466 | * desired filename 467 | * @param data 468 | * data 469 | * 470 | * @throws ExternalFileWriterException 471 | * if external storage is not available or free space is 472 | * less than size of the data 473 | */ 474 | public void writeDataToFile(File parent, String fileName, String data) 475 | throws ExternalFileWriterException { 476 | if (isExternalStorageAvailable(true)) { 477 | getAppDirectory(); 478 | 479 | File file = createFile(fileName, parent); 480 | 481 | writeDataToFile(file, data); 482 | } 483 | } 484 | 485 | /** 486 | * Writes data to the file. The file will be created in the directory name 487 | * same as app. 488 | *489 | * Name of the file will be the timestamp.extension 490 | *
491 | * 492 | * @param extension 493 | * extension of the file, pass null if you don't want to have 494 | * extension. 495 | * @param data 496 | * data to write 497 | * @param inCache 498 | * Pass true if you want to write data in External Cache. false if you want to write data in external directory. 499 | * 500 | * @throws ExternalFileWriterException 501 | * if external storage is not available or free space is 502 | * less than size of the data 503 | */ 504 | public void writeDataToTimeStampedFile(String extension, String data, boolean inCache) 505 | throws ExternalFileWriterException { 506 | if (isExternalStorageAvailable(true)) { 507 | getAppDirectory(); 508 | 509 | String fileExtension = (TextUtils.isEmpty(extension)) ? "" : "." + extension; 510 | String fileName = System.currentTimeMillis() + fileExtension; 511 | 512 | File file = createFile(fileName, getAppDirectory(inCache)); 513 | 514 | writeDataToFile(file, data); 515 | } 516 | } 517 | 518 | /** 519 | * Writes data to the file. The file will be created in the directory name 520 | * same as app. 521 | *522 | * Name of the file will be the timestamp.extension 523 | *
524 | * 525 | * @param parent 526 | * parent directory path 527 | * @param extension 528 | * extension of the file, pass null if you don't want to have 529 | * extension. 530 | * @param data 531 | * data to write 532 | * 533 | * @throws ExternalFileWriterException 534 | * if external storage is not available or free space is 535 | * less than size of the data 536 | */ 537 | public void writeDataToTimeStampedFile(File parent, String extension, String data) 538 | throws ExternalFileWriterException { 539 | if (isExternalStorageAvailable(true)) { 540 | getAppDirectory(); 541 | 542 | String fileExtension = (TextUtils.isEmpty(extension)) ? "" : "." + extension; 543 | String fileName = System.currentTimeMillis() + fileExtension; 544 | 545 | File file = createFile(fileName, parent); 546 | 547 | writeDataToFile(file, data); 548 | } 549 | } 550 | 551 | /** 552 | * Writes data to the file. The file will be created in the directory name 553 | * same as app. 554 | *555 | * Name of the file will be the timestamp.extension 556 | *
557 | * 558 | * @param extension 559 | * extension of the file, pass null if you don't want to have 560 | * extension. 561 | * @param data 562 | * data to write 563 | * 564 | * @throws ExternalFileWriterException 565 | * if external storage is not available or free space is 566 | * less than size of the data 567 | */ 568 | public void writeDataToTimeStampedFile(String extension, byte[] data, boolean inCache) 569 | throws ExternalFileWriterException { 570 | if (isExternalStorageAvailable(true)) { 571 | getAppDirectory(); 572 | 573 | String fileExtension = (TextUtils.isEmpty(extension)) ? "" : "." + extension; 574 | String fileName = System.currentTimeMillis() + fileExtension; 575 | 576 | File file = createFile(fileName, getAppDirectory(inCache)); 577 | 578 | writeDataToFile(file, data); 579 | } 580 | } 581 | 582 | /** 583 | * Writes data to the file. The file will be created in the directory name 584 | * same as app. 585 | *586 | * Name of the file will be the timestamp.extension 587 | *
588 | * 589 | * @param parent 590 | * parent directory path 591 | * @param extension 592 | * extension of the file, pass null if you don't want to have 593 | * extension. 594 | * @param data 595 | * data to write 596 | * 597 | * @throws ExternalFileWriterException 598 | * if external storage is not available or free space is 599 | * less than size of the data 600 | */ 601 | public void writeDataToTimeStampedFile(File parent, String extension, byte[] data) 602 | throws ExternalFileWriterException { 603 | if (isExternalStorageAvailable(true)) { 604 | getAppDirectory(); 605 | 606 | String fileExtension = (TextUtils.isEmpty(extension)) ? "" : "." + extension; 607 | String fileName = System.currentTimeMillis() + fileExtension; 608 | 609 | File file = createFile(fileName, parent); 610 | 611 | writeDataToFile(file, data); 612 | } 613 | } 614 | 615 | /** 616 | * Exception to report back developer about media state or storage state if 617 | * writing is not 618 | * possible 619 | */ 620 | public class ExternalFileWriterException 621 | extends Exception { 622 | 623 | public ExternalFileWriterException(String messege) { 624 | super(messege); 625 | } 626 | 627 | } 628 | } -------------------------------------------------------------------------------- /androidexternalfilewriter/src/main/java/com/celites/androidexternalfilewriter/ExternalFileWriterException.java: -------------------------------------------------------------------------------- 1 | package com.celites.androidexternalfilewriter; 2 | 3 | /** 4 | * Exception to report back developer about media state or storage state if writing is not possible 5 | */ 6 | public class ExternalFileWriterException 7 | extends Exception { 8 | 9 | public ExternalFileWriterException(String messege) { 10 | super(messege); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /androidexternalfilewriter/src/main/java/com/celites/androidexternalfilewriter/SAFFileWriter.java: -------------------------------------------------------------------------------- 1 | package com.celites.androidexternalfilewriter; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Activity; 5 | import android.content.Intent; 6 | import android.content.SharedPreferences; 7 | import android.net.Uri; 8 | import android.os.Build.VERSION_CODES; 9 | import android.os.ParcelFileDescriptor; 10 | import android.preference.PreferenceManager; 11 | import android.support.v4.content.ContextCompat; 12 | import android.support.v4.provider.DocumentFile; 13 | import android.text.TextUtils; 14 | import com.ceelites.devutils.ConstantMethods; 15 | import java.io.File; 16 | import java.io.FileNotFoundException; 17 | import java.io.FileOutputStream; 18 | import java.io.IOException; 19 | 20 | /** 21 | * Created by Prasham on 12/25/2015. 22 | */ 23 | @TargetApi(VERSION_CODES.LOLLIPOP) 24 | public class SAFFileWriter { 25 | 26 | private String PARENT_URI_KEY = "APP_EXTERNAL_PARENT_FILE_URI"; 27 | private Activity activity; 28 | private DocumentFile appCacheDirectory; 29 | private DocumentFile appDirectory; 30 | private DocumentFile externalCacheDirectory; 31 | private DocumentFile externalParentFile; 32 | private final SharedPreferences preferences; 33 | private int requestCode; 34 | private static final String canNotCreateDirectory = "Can not create directory: "; 35 | private static final String canNotWriteFile = "Can not write file: "; 36 | 37 | 38 | /** 39 | * Inits new SAFFileWriter object, it will first check whether we already have a parent directory with proper uri access or not. 40 | * 41 | * @param activity: 42 | * Activity for context and starting request for OPEN_DOCUMENT_TREE 43 | * @param requestCode: 44 | * Request code to listen to OPEN_DOCUMENT_TREE 45 | */ 46 | public SAFFileWriter(Activity activity, int requestCode) { 47 | this.activity = activity; 48 | this.requestCode = requestCode; 49 | File[] dirs = ContextCompat.getExternalCacheDirs(activity); 50 | if (dirs.length > 1) { 51 | File dir = dirs[1]; 52 | if (dir != null) { 53 | externalCacheDirectory = DocumentFile.fromFile(dir); 54 | } else { 55 | externalCacheDirectory = DocumentFile.fromFile(dirs[0]); 56 | } 57 | } else { 58 | externalCacheDirectory = DocumentFile.fromFile(dirs[0]); 59 | } 60 | preferences = PreferenceManager.getDefaultSharedPreferences(activity); 61 | String externalDirUrl = preferences.getString(PARENT_URI_KEY, ""); 62 | if (ConstantMethods.isEmptyString(externalDirUrl)) { 63 | Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); 64 | activity.startActivityForResult(intent, requestCode); 65 | } 66 | } 67 | 68 | /** 69 | * Creates subdirectory in parent directory 70 | * 71 | * @param parentDirectory 72 | * : Parent directory where directory with "directoryName" should be created 73 | * @param displayName 74 | * name of subdirectory 75 | * 76 | * @return File object of created subdirectory 77 | * 78 | * @throws ExternalFileWriterException 79 | * if external storage is not available 80 | */ 81 | public DocumentFile createSubDirectory(String displayName, DocumentFile parentDirectory) { 82 | getAppDirectory(); 83 | if (isDirectoryExists(displayName, parentDirectory)) { 84 | 85 | return parentDirectory.createDirectory(displayName); 86 | } else { 87 | return parentDirectory.findFile(displayName); 88 | } 89 | } 90 | 91 | /** 92 | * Get created app directory 93 | * 94 | * @return File object of created AppDirectory 95 | */ 96 | public DocumentFile getAppDirectory() { 97 | if (appDirectory == null) { 98 | createAppDirectory(); 99 | } 100 | return appDirectory; 101 | } 102 | 103 | /** 104 | * Check whether directory with given name exists in parentDirectory or not. 105 | * 106 | * @param directoryName 107 | * : Name of the directory to check. 108 | * @param parentDirectory 109 | * : Parent directory where directory with "directoryName" should be present 110 | * 111 | * @return true if a directory with "directoryName" exists, false otherwise 112 | */ 113 | public boolean isDirectoryExists(String displayName, DocumentFile parentDirectory) { 114 | DocumentFile file = parentDirectory.findFile(displayName); 115 | return file != null && file.isDirectory(); 116 | } 117 | 118 | /** Creates app directory */ 119 | private void createAppDirectory() { 120 | String directoryName = activity.getString(activity.getApplicationInfo().labelRes); 121 | appDirectory = externalParentFile.createDirectory(directoryName); 122 | appCacheDirectory = externalCacheDirectory.createDirectory(directoryName); 123 | } 124 | 125 | /** 126 | * Creates subdirectory in application directory 127 | * 128 | * @param directoryName 129 | * name of subdirectory 130 | * 131 | * @return File object of created subdirectory 132 | * 133 | * @throws ExternalFileWriterException 134 | * if external storage is not available 135 | */ 136 | public DocumentFile createSubdirectory(String directoryName, boolean inCache) { 137 | getAppDirectory(); 138 | DocumentFile appDirectory = getAppDirectory(inCache); 139 | if (!isDirectoryExists(directoryName, inCache)) { 140 | 141 | return appDirectory.createDirectory(directoryName); 142 | } else { 143 | return appDirectory.findFile(directoryName); 144 | } 145 | } 146 | 147 | public DocumentFile getAppDirectory(boolean inCache) { 148 | return (inCache) ? this.appCacheDirectory : this.appDirectory; 149 | } 150 | 151 | /** 152 | * Checks whether directory with given name exists in AppDirectory 153 | * 154 | * @param directoryName 155 | * : Name of the directory to check. 156 | * 157 | * @return true if a directory with "directoryName" exists, false otherwise 158 | */ 159 | public boolean isDirectoryExists(String displayName, boolean inCache) { 160 | DocumentFile file = getDocumentFile(displayName, inCache); 161 | return file != null && file.isDirectory(); 162 | } 163 | 164 | private DocumentFile getDocumentFile(String displayName, boolean inCache) { 165 | DocumentFile appDirectory = getAppDirectory(inCache); 166 | return appDirectory.findFile(displayName); 167 | } 168 | 169 | public void handleResult(int requestCode, int resultCode, Intent data) { 170 | if (resultCode == Activity.RESULT_OK) { 171 | if (requestCode == this.requestCode) { 172 | Uri treeUri = data.getData(); 173 | externalParentFile = DocumentFile.fromTreeUri(activity, treeUri); 174 | preferences.edit().putString(PARENT_URI_KEY, String.valueOf(externalParentFile.getUri())); 175 | getAppDirectory(); 176 | 177 | } 178 | } 179 | } 180 | 181 | /** 182 | * Check whether file with given name exists in parentDirectory or not. 183 | * 184 | * @param fileName 185 | * : Name of the file to check. 186 | * @param parentDirectory 187 | * : Parent directory where directory with "fileName" should be present 188 | * 189 | * @return true if a file with "fileName" exists, false otherwise 190 | */ 191 | public boolean isFileExists(String displayName, boolean inCache) { 192 | DocumentFile file = getDocumentFile(displayName, inCache); 193 | return file != null && file.isFile(); 194 | } 195 | 196 | public void writeDataToFile(String fileName, String mimeType, byte[] data, boolean inCache) throws FileNotFoundException { 197 | getAppDirectory(); 198 | DocumentFile appDir = getAppDirectory(inCache); 199 | writeDataToFile(appDir, fileName, data, mimeType); 200 | } 201 | 202 | /** 203 | * Writes data to the file. The file will be created in the directory name same as app. 204 | * 205 | * @param fileName 206 | * name of the file 207 | * @param data 208 | * data to write 209 | * 210 | * @throws ExternalFileWriterException 211 | * if external storage is not available or free space is less than size of the data 212 | */ 213 | public void writeDataToFile(DocumentFile parent, String fileName, byte[] data, String mimeType) throws FileNotFoundException { 214 | DocumentFile file = createFile(fileName, parent, mimeType); 215 | writeDataToFile(file, data); 216 | } 217 | 218 | private DocumentFile createFile(String fileName, DocumentFile parent, String mimeType) { 219 | if (!isFileExists(fileName, parent)) { 220 | 221 | return parent.createFile(mimeType, fileName); 222 | } else { 223 | return parent.findFile(fileName); 224 | } 225 | } 226 | 227 | /** 228 | * Write byte array to file. Will show error if given file is a directory. 229 | * 230 | * @param file 231 | * : File where data is to be written. 232 | * @param data 233 | * byte array which you want to write a file. If size of this is greater than size available, it will show error. 234 | */ 235 | private void writeDataToFile(DocumentFile file, byte[] data) throws FileNotFoundException { 236 | ParcelFileDescriptor fileDescriptor = activity.getContentResolver().openFileDescriptor(file.getUri(), "w"); 237 | FileOutputStream out = null; 238 | if (fileDescriptor != null) { 239 | out = new FileOutputStream(fileDescriptor.getFileDescriptor()); 240 | try { 241 | out.write(data); 242 | out.close(); 243 | } catch (IOException e) { 244 | e.printStackTrace(); 245 | } 246 | } 247 | } 248 | 249 | /** 250 | * Checks whether file with given name exists in AppDirectory 251 | * 252 | * @param fileName 253 | * : Name of the file to check. 254 | * 255 | * @return true if a file with "directoryName" exists, false otherwise 256 | */ 257 | public boolean isFileExists(String displayName, DocumentFile parentDirectory) { 258 | DocumentFile file = parentDirectory.findFile(displayName); 259 | return file != null && file.isFile(); 260 | } 261 | 262 | public void writeDataToFile(String fileName, String mimeType, String data, boolean inCache) throws FileNotFoundException { 263 | DocumentFile appDir = getAppDirectory(inCache); 264 | writeDataToFile(appDir, fileName, data, mimeType); 265 | } 266 | 267 | /** 268 | * Write data in file of a parent directory 269 | * 270 | * @param parent 271 | * parent directory 272 | * @param fileName 273 | * desired filename 274 | * @param data 275 | * data 276 | * 277 | * @throws ExternalFileWriterException 278 | * if external storage is not available or free space is less than size of the data 279 | */ 280 | public void writeDataToFile(DocumentFile parent, String fileName, String data, String mimeType) throws FileNotFoundException { 281 | DocumentFile file = createFile(fileName, parent, mimeType); 282 | writeDataToFile(file, data); 283 | } 284 | 285 | /** 286 | * Write byte array to file. Will show error if given file is a directory. 287 | * 288 | * @param file 289 | * : File where data is to be written. 290 | * @param data 291 | * String which you want to write a file. If size of this is greater than size available, it will show error. 292 | */ 293 | private void writeDataToFile(DocumentFile file, String data) throws FileNotFoundException { 294 | byte[] stringBuffer = data.getBytes(); 295 | writeDataToFile(file, stringBuffer); 296 | } 297 | 298 | public void writeDataToTimeStampedFile(String mimeType, String data, String extension, boolean inCache) throws FileNotFoundException { 299 | DocumentFile appDir = getAppDirectory(inCache); 300 | String fileExtension = (TextUtils.isEmpty(extension)) ? "" : "." + extension; 301 | String fileName = System.currentTimeMillis() + fileExtension; 302 | writeDataToFile(appDir, fileName, data, mimeType); 303 | } 304 | 305 | public void writeDataToTimeStampedFile(String mimeType, byte[] data, String extension, boolean inCache) throws FileNotFoundException { 306 | DocumentFile appDir = getAppDirectory(inCache); 307 | String fileExtension = (TextUtils.isEmpty(extension)) ? "" : "." + extension; 308 | String fileName = System.currentTimeMillis() + fileExtension; 309 | writeDataToFile(appDir, fileName, data, mimeType); 310 | } 311 | 312 | public void writeDataToTimeStampedFile(String mimeType, String data, String extension, boolean inCache, DocumentFile parent) throws 313 | FileNotFoundException { 314 | String fileExtension = (TextUtils.isEmpty(extension)) ? "" : "." + extension; 315 | String fileName = System.currentTimeMillis() + fileExtension; 316 | writeDataToFile(parent, fileName, data, mimeType); 317 | } 318 | 319 | public void writeDataToTimeStampedFile(String mimeType, byte[] data, String extension, boolean inCache, DocumentFile parent) throws 320 | FileNotFoundException { 321 | String fileExtension = (TextUtils.isEmpty(extension)) ? "" : "." + extension; 322 | String fileName = System.currentTimeMillis() + fileExtension; 323 | writeDataToFile(parent, fileName, data, mimeType); 324 | } 325 | 326 | private DocumentFile createFile(String fileName, boolean inCache, String mimeType) { 327 | return createFile(fileName, getAppDirectory(inCache), mimeType); 328 | } 329 | 330 | } 331 | -------------------------------------------------------------------------------- /androidexternalfilewriter/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 |