Back to project page android_device.
The source code is released under:
[Apache License](http://www.apache.org/licenses/): Version 2.0, January 2004 =============== ## TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION ## ### 1. Definitions. ### "License" sha...
If you think the Android project android_device listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * ================================================================================================= * Copyright (C) 2013 - 2014 Martin Albedinsky [Wolf-ITechnologies] * ================================================================================================= * Licensed under the Apache License, Version 2.0 or later (further "License" only). * ------------------------------------------------------------------------------------------------- * You may use this file only in compliance with the License. More details and copy of this License * you may obtain at/* ww w . ja va 2s . co m*/ * * http://www.apache.org/licenses/LICENSE-2.0 * * You can redistribute, modify or publish any part of the code written within this file but as it * is described in the License, the software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES or CONDITIONS OF ANY KIND. * * See the License for the specific language governing permissions and limitations under the License. * ================================================================================================= */ package com.wit.android.device; import android.content.Context; import android.os.Environment; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; import com.wit.android.device.util.StorageUtils; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * <h3>Class Overview</h3> * Implementation of {@link com.wit.android.device.Storage} wrapper for {@link com.wit.android.device.AndroidDevice AndroidDevice}. * * @author Martin Albedinsky */ class StorageImpl implements Storage { /** * Interface =================================================================================== */ /** * Constants =================================================================================== */ /** * Log TAG. */ private static final String TAG = "StorageImpl"; /** * Flag indicating whether the debug output trough log-cat is enabled or not. */ private static final boolean DEBUG_ENABLED = DeviceConfig.LIBRARY_DEBUG_LOG_ENABLED; /** * Flag indicating whether the output trough log-cat is enabled or not. */ // private static final boolean LOG_ENABLED = DeviceConfig.LIBRARY_LOG_ENABLED; /** * Relative path to the directory on the external storage where a directory named by the package * name of the current application should be created, so this application can store there its * own persistent data which will be deleted as soon as the application will be uninstalled. * <p> * Constant value: <b>Android/data</b> */ private static final String EXTERNAL_PACKAGE_STORAGE_PARENTS_PATH = "Android" + File.separator + "data"; /** * Static members ============================================================================== */ /** * Helper for create operations on files system. */ private final StorageAction SA_CREATE = new StorageAction.Create(this); /** * Helper for delete operations on file system. */ private final StorageAction SA_DELETE = new StorageAction.Delete(this); /** * Helper for copy operations on file system. */ private final StorageAction SA_COPY = new StorageAction.Copy(this); /** * Helper for move operations on file system. */ private final StorageAction SA_MOVE = new StorageAction.Move(this); /** * Members ===================================================================================== */ /** * Application context obtained from the context passed during initialization of this wrapper. */ private final Context mContext; /** * An application package name to create specific sub-directory in the external storage if it is * available. */ private String mPackageName; /** * File representing the root directory of the external file system. */ private File mExternal; /** * File representing the directory for the current application to store its data there. This * directory will be created only if {@link #getStorage(int)} is called with {@link #EXTERNAL_PACKAGE} * identifier and the external storage is at that particular time available. */ private File mExternalPackage; /** * Constructors ================================================================================ */ /** * Creates a new instance of StorageImpl wrapper with already initialized external storage * directory if it is available. * * @param context Application context or activity context. */ StorageImpl(Context context) { this.mContext = context.getApplicationContext(); // Save the package name. this.mPackageName = context.getPackageName(); // Check external storage state. // If the external storage is available, this also initialize external storage files. this.checkExternalAvailability(); } /** * Methods ===================================================================================== */ /** * Public -------------------------------------------------------------------------------------- */ /** */ @NonNull @Override public Result createFile(@NonNull String path) { return createFile(BASE, path); } /** */ @NonNull @Override public Result createFile(int storage, @NonNull String path) { if (StorageUtils.directoryExists(appendBasePath(storage, path))) { return StorageAction.createResult( ACTION_CREATE, "Failed to create file. Directory with this name already exists.", path, NO_FLAGS, ERROR_FILE_SAME_AS_DIRECTORY ); } return SA_CREATE.performFileAction(storage, NO_FLAGS, "", path); } /** */ @NonNull @Override public Results createFiles(@NonNull String... paths) { return createFiles(BASE, paths); } /** */ @NonNull @Override public Results createFiles(int storage, @NonNull String... paths) { return SA_CREATE.performFilesAction(storage, NO_FLAGS, "", paths); } /** */ @NonNull @Override public Result createDirectory(@NonNull String path) { return createDirectory(BASE, path); } /** */ @NonNull @Override public Result createDirectory(int storage, @NonNull String path) { if (StorageUtils.directoryExists(appendBasePath(storage, path))) { return StorageAction.createResult( ACTION_CREATE, "Failed to create file. Directory with this name already exists.", path, NO_FLAGS, ERROR_DIRECTORY_SAME_AS_FILE ); } return SA_CREATE.performDirectoryAction(storage, NO_FLAGS, null, null, "", path); } /** */ @NonNull @Override public Results createDirectories(@NonNull String... paths) { return createDirectories(BASE, paths); } /** */ @NonNull @Override public Results createDirectories(int storage, @NonNull String... paths) { return SA_CREATE.performDirectoriesAction(storage, NO_FLAGS, null, null, "", paths); } /** */ @NonNull @Override public Result deleteFile(@NonNull String path) { return deleteFile(BASE, path); } /** */ @NonNull @Override public Result deleteFile(int storage, @NonNull String path) { return SA_DELETE.performFileAction(storage, NO_FLAGS, "", path); } /** */ @NonNull @Override public Results deleteFiles(@NonNull String... paths) { return deleteFiles(BASE, paths); } /** */ @NonNull @Override public Results deleteFiles(int storage, @NonNull String... paths) { return SA_DELETE.performFilesAction(storage, NO_FLAGS, "", paths); } /** */ @NonNull @Override public Result deleteDirectory(@NonNull String path) { return deleteDirectory(BASE, path); } /** */ @NonNull @Override public Result deleteDirectory(int storage, @NonNull String path) { return deleteDirectory(storage, null, null, path); } /** */ @NonNull @Override public Result deleteDirectory(int storage, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @NonNull String path) { return SA_DELETE.performDirectoryAction(storage, NO_FLAGS, filter, nameFilter, "", path); } /** */ @NonNull @Override public Results deleteDirectories(@NonNull String... paths) { return deleteDirectories(BASE, paths); } /** */ @NonNull @Override public Results deleteDirectories(int storage, @NonNull String... paths) { return deleteDirectories(storage, null, null, paths); } /** */ @NonNull @Override public Results deleteDirectories(int storage, FileFilter filter, @Nullable FilenameFilter nameFilter, @NonNull String... paths) { return SA_DELETE.performDirectoriesAction(storage, NO_FLAGS, filter, nameFilter, "", paths); } /** */ @NonNull @Override public Result deleteFileOrDirectory(@NonNull String path) { return deleteFileOrDirectory(BASE, path); } /** */ @NonNull @Override public Result deleteFileOrDirectory(int storage, @NonNull String path) { return deleteFileOrDirectory(storage, null, null, path); } /** */ @NonNull @Override public Result deleteFileOrDirectory(int storage, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @NonNull String path) { return SA_DELETE.performFileOrDirectoryAction(storage, NO_FLAGS, filter, nameFilter, "", path); } /** */ @NonNull @Override public Results deleteFilesOrDirectories(@NonNull String... paths) { return deleteFilesOrDirectories(BASE, paths); } /** */ @NonNull @Override public Results deleteFilesOrDirectories(int storage, @NonNull String... paths) { return deleteFilesOrDirectories(storage, null, null, paths); } /** */ @NonNull @Override public Results deleteFilesOrDirectories(int storage, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @NonNull String... paths) { return SA_DELETE.performFilesOrDirectoriesAction(storage, NO_FLAGS, filter, nameFilter, "", paths); } /** */ @NonNull @Override public Result copyFile(int flags, @Nullable String toPath, @NonNull String fromPath) { return copyFile(BASE, flags, toPath, fromPath); } /** */ @NonNull @Override public Result copyFile(int storage, int flags, @Nullable String toPath, @NonNull String fromPath) { return SA_COPY.performFileAction(storage, flags, toPath, fromPath); } /** */ @NonNull @Override public Results copyFiles(int flags, @Nullable String toPath, @NonNull String... fromPaths) { return copyFiles(BASE, flags, toPath, fromPaths); } /** */ @NonNull @Override public Results copyFiles(int storage, int flags, @Nullable String toPath, @NonNull String... fromPaths) { return SA_DELETE.performFilesAction(storage, flags, toPath, fromPaths); } /** */ @NonNull @Override public Result copyDirectory(int flags, String toPath, @NonNull String fromPath) { return copyDirectory(BASE, flags, toPath, fromPath); } /** */ @NonNull @Override public Result copyDirectory(int storage, int flags, @Nullable String toPath, @NonNull String fromPath) { return copyDirectory(storage, flags, null, null, toPath, fromPath); } /** */ @NonNull @Override public Result copyDirectory(int storage, int flags, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @Nullable String toPath, @NonNull String fromPath) { return SA_DELETE.performDirectoryAction(storage, flags, filter, nameFilter, toPath, fromPath); } /** */ @NonNull @Override public Results copyDirectories(int flags, @Nullable String toPath, @NonNull String... fromPaths) { return copyDirectories(BASE, flags, toPath, fromPaths); } /** */ @NonNull @Override public Results copyDirectories(int storage, int flags, @Nullable String toPath, @NonNull String... fromPaths) { return copyDirectories(storage, flags, null, null, toPath, fromPaths); } /** */ @NonNull @Override public Results copyDirectories(int storage, int flags, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @Nullable String toPath, @NonNull String... fromPaths) { return SA_DELETE.performDirectoriesAction(storage, flags, filter, nameFilter, toPath, fromPaths); } /** */ @NonNull @Override public Result copyFileOrDirectory(int flags, @Nullable String toPath, @NonNull String fromPath) { return copyFileOrDirectory(BASE, flags, toPath, fromPath); } /** */ @NonNull @Override public Result copyFileOrDirectory(int storage, int flags, @Nullable String toPath, @NonNull String fromPath) { return copyFileOrDirectory(storage, flags, null, null, toPath, fromPath); } /** */ @NonNull @Override public Result copyFileOrDirectory(int storage, int flags, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @Nullable String toPath, @NonNull String fromPath) { return SA_COPY.performFileOrDirectoryAction(storage, flags, filter, nameFilter, toPath, fromPath); } /** */ @NonNull @Override public Results copyFilesOrDirectories(int flags, @Nullable String toPath, @NonNull String... fromPaths) { return copyFilesOrDirectories(BASE, flags, toPath, fromPaths); } /** */ @NonNull @Override public Results copyFilesOrDirectories(int storage, int flags, @Nullable String toPath, @NonNull String... fromPaths) { return copyFilesOrDirectories(storage, flags, null, null, toPath, fromPaths); } /** */ @NonNull @Override public Results copyFilesOrDirectories(int storage, int flags, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @Nullable String toPath, @NonNull String... fromPaths) { return SA_COPY.performFilesOrDirectoriesAction(storage, flags, filter, nameFilter, toPath, fromPaths); } /** */ @NonNull @Override public Result moveFile(int flags, @Nullable String toPath, @NonNull String fromPath) { return moveFile(BASE, flags, toPath, fromPath); } /** */ @NonNull @Override public Result moveFile(int storage, int flags, @Nullable String toPath, @NonNull String fromPath) { return SA_MOVE.performFileAction(storage, flags, toPath, fromPath); } /** */ @NonNull @Override public Results moveFiles(int flags, @Nullable String toPath, @NonNull String... fromPaths) { return moveFiles(BASE, flags, toPath, fromPaths); } /** */ @NonNull @Override public Results moveFiles(int storage, int flags, @Nullable String toPath, @NonNull String... fromPaths) { return SA_MOVE.performFilesAction(storage, flags, toPath, fromPaths); } @NonNull @Override public Result moveDirectory(int flags, @Nullable String toPath, @NonNull String fromPath) { return moveDirectory(BASE, flags, toPath, fromPath); } /** */ @NonNull @Override public Result moveDirectory(int storage, int flags, @Nullable String toPath, @NonNull String fromPath) { return moveDirectory(storage, flags, null, null, toPath, fromPath); } /** */ @NonNull @Override public Result moveDirectory(int storage, int flags, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @Nullable String toPath, @NonNull String fromPath) { return SA_MOVE.performDirectoryAction(storage, flags, filter, nameFilter, toPath, fromPath); } /** */ @NonNull @Override public Results moveDirectories(int flags, @Nullable String toPath, @NonNull String... fromPaths) { return moveDirectories(BASE, flags, toPath, fromPaths); } /** */ @NonNull @Override public Results moveDirectories(int storage, int flags, @Nullable String toPath, @NonNull String... fromPaths) { return moveDirectories(storage, flags, null, null, toPath, fromPaths); } /** */ @NonNull @Override public Results moveDirectories(int storage, int flags, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @Nullable String toPath, @NonNull String... fromPaths) { return SA_MOVE.performDirectoriesAction(storage, flags, filter, nameFilter, toPath, fromPaths); } @NonNull @Override public Result moveFileOrDirectory(int flags, @Nullable String toPath, @NonNull String fromPath) { return moveFileOrDirectory(BASE, flags, toPath, fromPath); } /** */ @NonNull @Override public Result moveFileOrDirectory(int storage, int flags, @Nullable String toPath, @NonNull String fromPath) { return moveFileOrDirectory(storage, flags, null, null, toPath, fromPath); } /** */ @NonNull @Override public Result moveFileOrDirectory(int storage, int flags, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @Nullable String toPath, @NonNull String fromPath) { return SA_MOVE.performFileOrDirectoryAction(storage, flags, filter, nameFilter, toPath, fromPath); } /** */ @NonNull @Override public Results moveFilesOrDirectories(int flags, @Nullable String toPath, @NonNull String... fromPaths) { return moveFilesOrDirectories(BASE, flags, toPath, fromPaths); } /** */ @NonNull @Override public Results moveFilesOrDirectories(int storage, int flags, @Nullable String toPath, @NonNull String... fromPaths) { return moveFilesOrDirectories(storage, flags, null, null, toPath, fromPaths); } /** */ @NonNull @Override public Results moveFilesOrDirectories(int storage, int flags, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @Nullable String toPath, @NonNull String... fromPaths) { return SA_MOVE.performFilesOrDirectoriesAction(storage, flags, filter, nameFilter, toPath, fromPaths); } /** */ @Override public boolean changeFilePermissions(@NonNull String path, int permissions, boolean ownerOnly) { return changeFilePermissions(BASE, path, permissions, ownerOnly); } /** */ @Override public boolean changeFilePermissions(int storage, @NonNull String path, int permissions, boolean ownerOnly) { final File file = this.newFile(storage, path); if (file.isFile() && permissions > 0) { if (file.setExecutable((permissions & PERMISSION_EXECUTE) != 0, ownerOnly) && file.setWritable((permissions & PERMISSION_WRITE) != 0, ownerOnly) && file.setReadable((permissions & PERMISSION_READ) != 0, ownerOnly)) { return true; } Log.e(TAG, "Failed to change read/write/execute permissions(" + permissions + ") of file('" + file.getPath() + "')."); } return false; } /** */ @Override public boolean isExternalReadOnly() { return Environment.MEDIA_MOUNTED_READ_ONLY.equals(Environment.getExternalStorageState()); } /** */ @Override public boolean isExternalMounted() { return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); } /** */ @Override public boolean isExternalAvailable() { return checkExternalAvailability(); } /** */ @Override public boolean hasFreeSpace(int storage, long bytes) { final File storageFile = getStorage(storage); return storageFile != null && storageFile.getFreeSpace() >= bytes; } /** * Getters + Setters --------------------------------------------------------------------------- */ /** */ @Override public long getFreeSpace(int storage) { final File storageFile = getStorage(storage); return storageFile != null ? storageFile.getFreeSpace() : 0; } /** */ @Nullable @Override public File getStorage(int storage) { switch (storage) { case INTERNAL: return mContext.getFilesDir(); case EXTERNAL: if (checkExternalAvailability()) { return mExternal; } break; case EXTERNAL_PACKAGE: if (checkExternalAvailability() && createExternalPackageDir()) { return mExternalPackage; } break; case ROOT: return Environment.getRootDirectory(); case DATA: return Environment.getDataDirectory(); case CACHE: return mContext.getCacheDir(); } return null; } /** */ @NonNull @Override public String getStoragePath(int storage) { if (storage == BASE) { return ""; } final File storageFile = getStorage(storage); return storageFile != null ? storageFile.getPath() : ""; } /** */ @NonNull @Override public File getFile(String path, int storage) { return this.newFile(storage, path); } /** */ @NonNull @Override public List<File> getDirectoryContent(@NonNull String path) { return getDirectoryContent(BASE, path); } /** */ @NonNull @Override public List<File> getDirectoryContent(int storage, @NonNull String path) { return getDirectoryContent(storage, null, null, path); } /** */ @NonNull @Override public List<File> getDirectoryContent(int storage, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @NonNull String path) { final File dir = this.newFile(storage, path); if (dir.isDirectory()) { if (filter == null) { final File[] files = dir.listFiles(nameFilter); return !isArrayEmpty(files) ? Arrays.asList(files) : new ArrayList<File>(0); } else { // First, filter by file. final File[] filteredFiles = dir.listFiles(filter); if (!isArrayEmpty(filteredFiles)) { if (nameFilter != null) { final List<File> files = new ArrayList<>(); // Now filter by name. for (File file : filteredFiles) { if (nameFilter.accept(file, file.getName())) { files.add(file); } } return files; } return Arrays.asList(filteredFiles); } } } else { this.logMessage( "Can not to obtain content of directory. Directory(" + dir.getPath() + ") does not exists or is not a directory.", true ); } return new ArrayList<>(); } /** */ @NonNull @Override public List<File> getDirectoriesContent(@NonNull String... paths) { return getDirectoriesContent(BASE, paths); } /** */ @NonNull @Override public List<File> getDirectoriesContent(int storage, @NonNull String... paths) { return getDirectoriesContent(storage, null, null, paths); } /** */ @NonNull @Override public List<File> getDirectoriesContent(int storage, @Nullable FileFilter filter, @Nullable FilenameFilter nameFilter, @NonNull String... paths) { final List<File> files = new ArrayList<>(); if (paths.length > 0) { for (String path : paths) { files.addAll(getDirectoryContent(storage, filter, nameFilter, path)); } return files; } return files; } /** * Protected ----------------------------------------------------------------------------------- */ /** * Returns a name of storage type represented by the specified <var>storage</var> identifier. * * @param storage An identifier of the desired storage of which name is requested. * @return Storage name or {@code ""} if unknown type or {@link #BASE} was requested. */ static String getStorageName(int storage) { switch (storage) { case INTERNAL: return "INTERNAL"; case EXTERNAL: return "EXTERNAL"; case EXTERNAL_PACKAGE: return "EXTERNAL_PACKAGE"; case ROOT: return "ROOT"; case DATA: return "DATA"; case CACHE: return "CACHE"; } return ""; } /** * Appends the path obtained by {@link #getStoragePath(int)} by the given <var>path</var>. * * @param storage An identifier of the desired storage of which path to use as base path. * @param path The desired path which should be appended to the base path. * @return Appended base path of the specified storage with the given path or just the given * <var>path</var> if the path of the specified storage is empty. */ String appendBasePath(int storage, String path) { final String basePath = getStoragePath(storage); return !TextUtils.isEmpty(basePath) ? basePath + File.separator + path : path; } /** * Private ------------------------------------------------------------------------------------- */ /** * Checks whether the external storage is available or not. See {@link android.os.Environment#getExternalStorageState()} * for more info. * <p> * <b>Note</b>, that in case that the external storage is available, this will also initialize file * for external dir and also, create sub-directory in the Android/data/ directory for the * current application package name. * * @return {@code True} if external storage is <b>MOUNTED</b> or <b>MOUNTED_READ_ONLY</b>. */ private boolean checkExternalAvailability() { String status; boolean available; final String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { if (mExternal == null) { this.mExternal = Environment.getExternalStorageDirectory(); } status = "available"; available = true; } else { this.mExternal = null; this.mExternalPackage = null; status = "not available"; available = false; } this.logMessage("External storage is " + status + ".", false); return available; } /** * Creates a directory on the external storage for the current application <var>mPackageName</var> * if it is not created yet. * <p> * Directory will be created with the path: {@link #EXTERNAL_PACKAGE_STORAGE_PARENTS_PATH} + mPackageName, * so for example for application with package name {@code com.google.docs}, this will create * a directory with path {@code Android/data/com.google.docs/}. * * @return {@code True} if directory was successfully created or was already created, * {@code false} if the external storage is not available at this time. */ private boolean createExternalPackageDir() { if (mExternalPackage != null) { return true; } if (mExternal != null) { // Build the path to the external storage directory specific of the package name of // this application. this.mExternalPackage = new File(mExternal.getPath() + File.separator + EXTERNAL_PACKAGE_STORAGE_PARENTS_PATH + File.separator + mPackageName ); // Create if not exists. if (!mExternalPackage.exists() && !mExternalPackage.mkdirs()) { this.logMessage( "Failed to create external directory(" + mExternalPackage.getPath() + ") for package(" + mPackageName + ")." + "Check your manifest for \"android.permission.WRITE_EXTERNAL_STORAGE\" permission.", true ); this.mExternalPackage = null; } return true; } return false; } /** * Builds the full path from the given path and the path of the given <var>storage</var> type. * * @param storage Type of storage of which path should be used as base for the requested path. * @param path Relative path to be appended to the path of resolved <var>storage</var> type. * @return Full path. */ private String buildPath(int storage, String path) { return getStoragePath(storage) + File.separator + path; } /** * Creates a new file with the path created from the given relative <var>path</var> and path * of the specified <var>storage</var> as base path. * * @param storage Type of storage of which path should be used as base for the requested file's * path. * @param path Relative path to be appended to the path of resolved <var>storage</var> type. * @return An instance of file the the requested path. */ private File newFile(int storage, String path) { return new File(buildPath(storage, path)); } /** * Logs the given message using {@link android.util.Log} util. * * @param message Message to log. * @param error {@code True} to log message as error, {@code false}otherwise. */ private void logMessage(String message, boolean error) { if (error) { Log.e(TAG, message); } else if (DEBUG_ENABLED) { Log.v(TAG, message); } } /** * Checks whether the given array is empty or not. * * @param array Array to check. * @return {@code True} if the given array is {@code null} or if it doesn't have any * items within it, {@code false} otherwise. */ private boolean isArrayEmpty(Object[] array) { return array == null || array.length == 0; } /** * Inner classes =============================================================================== */ }