diff options
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/app/ContextImpl.java | 59 | ||||
-rw-r--r-- | core/java/android/app/IntentService.java | 2 | ||||
-rw-r--r-- | core/java/android/content/Context.java | 132 | ||||
-rw-r--r-- | core/java/android/content/ContextWrapper.java | 10 | ||||
-rw-r--r-- | core/java/android/content/pm/IPackageManager.aidl | 1 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageManager.java | 7 | ||||
-rw-r--r-- | core/java/android/os/Environment.java | 182 |
7 files changed, 385 insertions, 8 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 4923eee..9b9cbd5 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -197,9 +197,9 @@ class ContextImpl extends Context { private File mDatabasesDir; private File mPreferencesDir; private File mFilesDir; - - private File mCacheDir; + private File mExternalFilesDir; + private File mExternalCacheDir; private static long sInstanceCount = 0; @@ -438,6 +438,38 @@ class ContextImpl extends Context { } @Override + public File getExternalFilesDir(String type) { + synchronized (mSync) { + if (mExternalFilesDir == null) { + mExternalFilesDir = Environment.getExternalStorageAppFilesDirectory( + getPackageName()); + } + if (!mExternalFilesDir.exists()) { + try { + (new File(Environment.getExternalStorageAndroidDataDir(), + ".nomedia")).createNewFile(); + } catch (IOException e) { + } + if (!mExternalFilesDir.mkdirs()) { + Log.w(TAG, "Unable to create external files directory"); + return null; + } + } + if (type == null) { + return mExternalFilesDir; + } + File dir = new File(mExternalFilesDir, type); + if (!dir.exists()) { + if (!dir.mkdirs()) { + Log.w(TAG, "Unable to create external media directory " + dir); + return null; + } + } + return dir; + } + } + + @Override public File getCacheDir() { synchronized (mSync) { if (mCacheDir == null) { @@ -457,7 +489,28 @@ class ContextImpl extends Context { return mCacheDir; } - + @Override + public File getExternalCacheDir() { + synchronized (mSync) { + if (mExternalCacheDir == null) { + mExternalCacheDir = Environment.getExternalStorageAppCacheDirectory( + getPackageName()); + } + if (!mExternalCacheDir.exists()) { + try { + (new File(Environment.getExternalStorageAndroidDataDir(), + ".nomedia")).createNewFile(); + } catch (IOException e) { + } + if (!mExternalCacheDir.mkdirs()) { + Log.w(TAG, "Unable to create external cache directory"); + return null; + } + } + return mExternalCacheDir; + } + } + @Override public File getFileStreamPath(String name) { return makeFilename(getFilesDir(), name); diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java index 804c8eb..3fd36a3 100644 --- a/core/java/android/app/IntentService.java +++ b/core/java/android/app/IntentService.java @@ -42,7 +42,7 @@ public abstract class IntentService extends Service { * {@link #onStartCommand(Intent, int, int)} will return * {@link Service#START_REDELIVER_INTENT} instead of * {@link Service#START_NOT_STICKY}, so that if this service's process - * is called while it is executing the Intent in + * is killed while it is executing the Intent in * {@link #onHandleIntent(Intent)}, then when later restarted the same Intent * will be re-delivered to it, to retry its execution. */ diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index b4a0bf8..672e5f7 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -25,6 +25,7 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; +import android.media.MediaScannerConnection.ScanResultListener; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -137,7 +138,28 @@ public abstract class Context { /** * Return the context of the single, global Application object of the - * current process. + * current process. This generally should only be used if you need a + * Context whose lifecycle is separate from the current context, that is + * tied to the lifetime of the process rather than the current component. + * + * <p>Consider for example how this interacts with + * {@ #registerReceiver(BroadcastReceiver, IntentFilter)}: + * <ul> + * <li> <p>If used from an Activity context, the receiver is being registered + * within that activity. This means that you are expected to unregister + * before the activity is done being destroyed; in fact if you do not do + * so, the framework will clean up your leaked registration as it removes + * the activity and log an error. Thus, if you use the Activity context + * to register a receiver that is static (global to the process, not + * associated with an Activity instance) then that registration will be + * removed on you at whatever point the activity you used is destroyed. + * <li> <p>If used from the Context returned here, the receiver is being + * registered with the global state associated with your application. Thus + * it will never be unregistered for you. This is necessary if the receiver + * is associated with static data, not a particular component. However + * using the ApplicationContext elsewhere can easily lead to serious leaks + * if you forget to unregister, unbind, etc. + * </ul> */ public abstract Context getApplicationContext(); @@ -393,11 +415,84 @@ public abstract class Context { public abstract File getFilesDir(); /** + * Returns the absolute path to the directory on the external filesystem + * (that is somewhere on {@link android.os.Environment#getExternalStorageDirectory() + * Environment.getExternalStorageDirectory()} where the application can + * place persistent files it owns. These files are private to the + * applications, and not typically visible to the user as media. + * + * <p>This is like {@link #getFilesDir()} in that these + * files will be deleted when the application is uninstalled, however there + * are some important differences: + * + * <ul> + * <li>External files are not always available: they will disappear if the + * user mounts the external storage on a computer or removes it. See the + * APIs on {@link android.os.Environment} for information in the storage state. + * <li>There is no security enforced with these files. All applications + * can read and write files placed here. + * </ul> + * + * <p>Here is an example of typical code to manipulate a file in + * an application's private storage:</p> + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java + * private_file} + * + * <p>If you install a non-null <var>type</var> to this function, the returned + * file will be a path to a sub-directory of the given type. Though these files + * are not automatically scanned by the media scanner, you can explicitly + * add them to the media database with + * {@link android.media.MediaScannerConnection#scanFile(Context, String[], String[], + * ScanResultListener) MediaScannerConnection.scanFile}. + * Note that this is not the same as + * {@link android.os.Environment#getExternalStoragePublicDirectory + * Environment.getExternalStoragePublicDirectory()}, which provides + * directories of media shared by all applications. The + * directories returned here are + * owned by the application, and its contents will be removed when the + * application is uninstalled. Unlike + * {@link android.os.Environment#getExternalStoragePublicDirectory + * Environment.getExternalStoragePublicDirectory()}, the directory + * returned here will be automatically created for you. + * + * <p>Here is an example of typical code to manipulate a picture in + * an application's private storage and add it to the media database:</p> + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java + * private_picture} + * + * @param type The type of files directory to return. May be null for + * the root of the files directory or one of + * the following Environment constants for a subdirectory: + * {@link android.os.Environment#DIRECTORY_MUSIC}, + * {@link android.os.Environment#DIRECTORY_PODCASTS}, + * {@link android.os.Environment#DIRECTORY_RINGTONES}, + * {@link android.os.Environment#DIRECTORY_ALARMS}, + * {@link android.os.Environment#DIRECTORY_NOTIFICATIONS}, + * {@link android.os.Environment#DIRECTORY_PICTURES}, or + * {@link android.os.Environment#DIRECTORY_MOVIES}. + * + * @return Returns the path of the directory holding application files + * on external storage. Returns null if external storage is not currently + * mounted so it could not ensure the path exists; you will need to call + * this method again when it is available. + * + * @see #getFilesDir + */ + public abstract File getExternalFilesDir(String type); + + /** * Returns the absolute path to the application specific cache directory * on the filesystem. These files will be ones that get deleted first when the - * device runs low on storage + * device runs low on storage. * There is no guarantee when these files will be deleted. - * + * + * <strong>Note: you should not <em>rely</em> on the system deleting these + * files for you; you should always have a reasonable maximum, such as 1 MB, + * for the amount of space you consume with cache files, and prune those + * files when exceeding that space.</strong> + * * @return Returns the path of the directory holding application cache files. * * @see #openFileOutput @@ -407,6 +502,37 @@ public abstract class Context { public abstract File getCacheDir(); /** + * Returns the absolute path to the directory on the external filesystem + * (that is somewhere on {@link android.os.Environment#getExternalStorageDirectory() + * Environment.getExternalStorageDirectory()} where the application can + * place cache files it owns. + * + * <p>This is like {@link #getCacheDir()} in that these + * files will be deleted when the application is uninstalled, however there + * are some important differences: + * + * <ul> + * <li>The platform does not monitor the space available in external storage, + * and thus will not automatically delete these files. Note that you should + * be managing the maximum space you will use for these anyway, just like + * with {@link #getCacheDir()}. + * <li>External files are not always available: they will disappear if the + * user mounts the external storage on a computer or removes it. See the + * APIs on {@link android.os.Environment} for information in the storage state. + * <li>There is no security enforced with these files. All applications + * can read and write files placed here. + * </ul> + * + * @return Returns the path of the directory holding application cache files + * on external storage. Returns null if external storage is not currently + * mounted so it could not ensure the path exists; you will need to call + * this method again when it is available. + * + * @see #getCacheDir + */ + public abstract File getExternalCacheDir(); + + /** * Returns an array of strings naming the private files associated with * this Context's application package. * diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 1b34320..a447108 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -179,11 +179,21 @@ public class ContextWrapper extends Context { } @Override + public File getExternalFilesDir(String type) { + return mBase.getExternalFilesDir(type); + } + + @Override public File getCacheDir() { return mBase.getCacheDir(); } @Override + public File getExternalCacheDir() { + return mBase.getExternalCacheDir(); + } + + @Override public File getDir(String name, int mode) { return mBase.getDir(name, mode); } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 54db5e0..2c8c112 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -305,4 +305,5 @@ interface IPackageManager { */ void updateExternalMediaStatus(boolean mounted); + String nextPackageToClean(String lastPackage); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e3b1694..fca8588 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -622,6 +622,13 @@ public abstract class PackageManager { public static final String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper"; /** + * Action to external storage service to clean out removed apps. + * @hide + */ + public static final String ACTION_CLEAN_EXTERNAL_STORAGE + = "android.content.pm.CLEAN_EXTERNAL_STORAGE"; + + /** * Determines best place to install an application: either SD or internal FLASH. * Tweak the algorithm for best results. * @param appInfo ApplicationInfo object of the package to install. diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index ef1f3be..a9831aa 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -91,6 +91,14 @@ public class Environment { private static final File EXTERNAL_STORAGE_DIRECTORY = getDirectory("EXTERNAL_STORAGE", "/sdcard"); + private static final File EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY + = new File (new File(getDirectory("EXTERNAL_STORAGE", "/sdcard"), + "Android"), "data"); + + private static final File EXTERNAL_STORAGE_ANDROID_MEDIA_DIRECTORY + = new File (new File(getDirectory("EXTERNAL_STORAGE", "/sdcard"), + "Android"), "media"); + private static final File DOWNLOAD_CACHE_DIRECTORY = getDirectory("DOWNLOAD_CACHE", "/cache"); @@ -102,13 +110,183 @@ public class Environment { } /** - * Gets the Android external storage directory. + * Gets the Android external storage directory. This directory may not + * currently be accessible if it has been mounted by the user on their + * computer, has been removed from the device, or some other problem has + * happened. You can determine its current state with + * {@link #getExternalStorageState()}. + * + * <p>Here is an example of typical code to monitor the state of + * external storage:</p> + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java + * monitor_storage} */ public static File getExternalStorageDirectory() { return EXTERNAL_STORAGE_DIRECTORY; } /** + * Standard directory in which to place any audio files that should be + * in the regular list of music for the user. + * This may be combined with + * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, + * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series + * of directories to categories a particular audio file as more than one + * type. + */ + public static String DIRECTORY_MUSIC = "Music"; + + /** + * Standard directory in which to place any audio files that should be + * in the list of podcasts that the user can select (not as regular + * music). + * This may be combined with {@link #DIRECTORY_MUSIC}, + * {@link #DIRECTORY_NOTIFICATIONS}, + * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series + * of directories to categories a particular audio file as more than one + * type. + */ + public static String DIRECTORY_PODCASTS = "Podcasts"; + + /** + * Standard directory in which to place any audio files that should be + * in the list of ringtones that the user can select (not as regular + * music). + * This may be combined with {@link #DIRECTORY_MUSIC}, + * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, and + * {@link #DIRECTORY_ALARMS} as a series + * of directories to categories a particular audio file as more than one + * type. + */ + public static String DIRECTORY_RINGTONES = "Ringtones"; + + /** + * Standard directory in which to place any audio files that should be + * in the list of alarms that the user can select (not as regular + * music). + * This may be combined with {@link #DIRECTORY_MUSIC}, + * {@link #DIRECTORY_PODCASTS}, {@link #DIRECTORY_NOTIFICATIONS}, + * and {@link #DIRECTORY_RINGTONES} as a series + * of directories to categories a particular audio file as more than one + * type. + */ + public static String DIRECTORY_ALARMS = "Alarms"; + + /** + * Standard directory in which to place any audio files that should be + * in the list of notifications that the user can select (not as regular + * music). + * This may be combined with {@link #DIRECTORY_MUSIC}, + * {@link #DIRECTORY_PODCASTS}, + * {@link #DIRECTORY_ALARMS}, and {@link #DIRECTORY_RINGTONES} as a series + * of directories to categories a particular audio file as more than one + * type. + */ + public static String DIRECTORY_NOTIFICATIONS = "Notifications"; + + /** + * Standard directory in which to place pictures that are available to + * the user. Note that this is primarily a convention for the top-level + * public directory, as the media scanner will find and collect pictures + * in any directory. + */ + public static String DIRECTORY_PICTURES = "Pictures"; + + /** + * Standard directory in which to place movies that are available to + * the user. Note that this is primarily a convention for the top-level + * public directory, as the media scanner will find and collect movies + * in any directory. + */ + public static String DIRECTORY_MOVIES = "Movies"; + + /** + * Standard directory in which to place files that have been downloaded by + * the user. Note that this is primarily a convention for the top-level + * public directory, you are free to download files anywhere in your own + * private directories. + */ + public static String DIRECTORY_DOWNLOADS = "Downloads"; + + /** + * The traditional location for pictures and videos when mounting the + * device as a camera. Note that this is primarily a convention for the + * top-level public directory, as this convention makes no sense elsewhere. + */ + public static String DIRECTORY_DCIM = "DCIM"; + + /** + * Get a top-level public external storage directory for placing files of + * a particular type. This is where the user will typically place and + * manage their own files, so you should be careful about what you put here + * to ensure you don't erase their files or get in the way of their own + * organization. + * + * <p>Here is an example of typical code to manipulate a picture on + * the public external storage:</p> + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java + * public_picture} + * + * @param type The type of storage directory to return. Should be one of + * {@link #DIRECTORY_MUSIC}, {@link #DIRECTORY_PODCASTS}, + * {@link #DIRECTORY_RINGTONES}, {@link #DIRECTORY_ALARMS}, + * {@link #DIRECTORY_NOTIFICATIONS}, {@link #DIRECTORY_PICTURES}, + * {@link #DIRECTORY_MOVIES}, {@link #DIRECTORY_DOWNLOADS}, or + * {@link #DIRECTORY_DCIM}. May not be null. + * + * @return Returns the File path for the directory. Note that this + * directory may not yet exist, so you must make sure it exists before + * using it such as with {@link File#mkdirs File.mkdirs()}. + */ + public static File getExternalStoragePublicDirectory(String type) { + return new File(getExternalStorageDirectory(), type); + } + + /** + * Returns the path for android-specific data on the SD card. + * @hide + */ + public static File getExternalStorageAndroidDataDir() { + return EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY; + } + + /** + * Generates the raw path to an application's data + * @hide + */ + public static File getExternalStorageAppDataDirectory(String packageName) { + return new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY, packageName); + } + + /** + * Generates the raw path to an application's media + * @hide + */ + public static File getExternalStorageAppMediaDirectory(String packageName) { + return new File(EXTERNAL_STORAGE_ANDROID_MEDIA_DIRECTORY, packageName); + } + + /** + * Generates the path to an application's files. + * @hide + */ + public static File getExternalStorageAppFilesDirectory(String packageName) { + return new File(new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY, + packageName), "files"); + } + + /** + * Generates the path to an application's cache. + * @hide + */ + public static File getExternalStorageAppCacheDirectory(String packageName) { + return new File(new File(EXTERNAL_STORAGE_ANDROID_DATA_DIRECTORY, + packageName), "cache"); + } + + /** * Gets the Android Download/Cache content directory. */ public static File getDownloadCacheDirectory() { @@ -173,6 +351,8 @@ public class Environment { * Gets the current state of the external storage device. * Note: This call should be deprecated as it doesn't support * multiple volumes. + * + * <p>See {@link #getExternalStorageDirectory()} for an example of its use. */ public static String getExternalStorageState() { try { |