diff options
Diffstat (limited to 'core/java/android/content/ContentResolver.java')
-rw-r--r-- | core/java/android/content/ContentResolver.java | 320 |
1 files changed, 90 insertions, 230 deletions
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 0d886ee..52f55b6 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -17,7 +17,6 @@ package android.content; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.database.ContentObserver; import android.database.Cursor; @@ -29,7 +28,6 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.text.TextUtils; -import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; @@ -172,100 +170,119 @@ public abstract class ContentResolver { * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li> * <li>file ({@link #SCHEME_FILE})</li> * </ul> - * - * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information - * on these schemes. - * - * @param uri The desired URI. + * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5> + * <p> + * A Uri object can be used to reference a resource in an APK file. The + * Uri should be one of the following formats: + * <ul> + * <li><code>android.resource://package_name/id_number</code><br/> + * <code>package_name</code> is your package name as listed in your AndroidManifest.xml. + * For example <code>com.example.myapp</code><br/> + * <code>id_number</code> is the int form of the ID.<br/> + * The easiest way to construct this form is + * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre> + * </li> + * <li><code>android.resource://package_name/type/name</code><br/> + * <code>package_name</code> is your package name as listed in your AndroidManifest.xml. + * For example <code>com.example.myapp</code><br/> + * <code>type</code> is the string form of the resource type. For example, <code>raw</code> + * or <code>drawable</code>. + * <code>name</code> is the string form of the resource name. That is, whatever the file + * name was in your res directory, without the type extension. + * The easiest way to construct this form is + * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre> + * </li> + * </ul> + * @param uri The desired "content:" URI. * @return InputStream * @throws FileNotFoundException if the provided URI could not be opened. - * @see #openAssetFileDescriptor(Uri, String) */ public final InputStream openInputStream(Uri uri) throws FileNotFoundException { String scheme = uri.getScheme(); - if (SCHEME_ANDROID_RESOURCE.equals(scheme)) { - // Note: left here to avoid breaking compatibility. May be removed - // with sufficient testing. - OpenResourceIdResult r = getResourceId(uri); + if (SCHEME_CONTENT.equals(scheme)) { + ParcelFileDescriptor fd = openFileDescriptor(uri, "r"); + return fd != null ? new ParcelFileDescriptor.AutoCloseInputStream(fd) : null; + } else if (SCHEME_ANDROID_RESOURCE.equals(scheme)) { + String authority = uri.getAuthority(); + Resources r; + if (TextUtils.isEmpty(authority)) { + throw new FileNotFoundException("No authority: " + uri); + } else { + try { + r = mContext.getPackageManager().getResourcesForApplication(authority); + } catch (NameNotFoundException ex) { + throw new FileNotFoundException("No package found for authority: " + uri); + } + } + List<String> path = uri.getPathSegments(); + if (path == null) { + throw new FileNotFoundException("No path: " + uri); + } + int len = path.size(); + int id; + if (len == 1) { + try { + id = Integer.parseInt(path.get(0)); + } catch (NumberFormatException e) { + throw new FileNotFoundException("Single path segment is not a resource ID: " + uri); + } + } else if (len == 2) { + id = r.getIdentifier(path.get(1), path.get(0), authority); + } else { + throw new FileNotFoundException("More than two path segments: " + uri); + } + if (id == 0) { + throw new FileNotFoundException("No resource found for: " + uri); + } try { - InputStream stream = r.r.openRawResource(r.id); + InputStream stream = r.openRawResource(id); return stream; } catch (Resources.NotFoundException ex) { - throw new FileNotFoundException("Resource does not exist: " + uri); + throw new FileNotFoundException("Resource ID does not exist: " + uri); } } else if (SCHEME_FILE.equals(scheme)) { - // Note: left here to avoid breaking compatibility. May be removed - // with sufficient testing. return new FileInputStream(uri.getPath()); } else { - AssetFileDescriptor fd = openAssetFileDescriptor(uri, "r"); - try { - return fd != null ? fd.createInputStream() : null; - } catch (IOException e) { - throw new FileNotFoundException("Unable to create stream"); - } + throw new FileNotFoundException("Unknown scheme: " + uri); } } /** - * Synonym for {@link #openOutputStream(Uri, String) - * openOutputStream(uri, "w")}. - * @throws FileNotFoundException if the provided URI could not be opened. - */ - public final OutputStream openOutputStream(Uri uri) - throws FileNotFoundException { - return openOutputStream(uri, "w"); - } - - /** * Open a stream on to the content associated with a content URI. If there * is no data associated with the URI, FileNotFoundException is thrown. * * <h5>Accepts the following URI schemes:</h5> * <ul> * <li>content ({@link #SCHEME_CONTENT})</li> - * <li>file ({@link #SCHEME_FILE})</li> * </ul> * - * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information - * on these schemes. - * - * @param uri The desired URI. - * @param mode May be "w", "wa", "rw", or "rwt". + * @param uri The desired "content:" URI. * @return OutputStream - * @throws FileNotFoundException if the provided URI could not be opened. - * @see #openAssetFileDescriptor(Uri, String) */ - public final OutputStream openOutputStream(Uri uri, String mode) + public final OutputStream openOutputStream(Uri uri) throws FileNotFoundException { - AssetFileDescriptor fd = openAssetFileDescriptor(uri, mode); - try { - return fd != null ? fd.createOutputStream() : null; - } catch (IOException e) { - throw new FileNotFoundException("Unable to create stream"); + String scheme = uri.getScheme(); + if (SCHEME_CONTENT.equals(scheme)) { + ParcelFileDescriptor fd = openFileDescriptor(uri, "rw"); + return fd != null + ? new ParcelFileDescriptor.AutoCloseOutputStream(fd) : null; + } else { + throw new FileNotFoundException("Unknown scheme: " + uri); } } /** * Open a raw file descriptor to access data under a "content:" URI. This - * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the - * underlying {@link ContentProvider#openFile} - * ContentProvider.openFile()} method, so will <em>not</em> work with - * providers that return sub-sections of files. If at all possible, - * you should use {@link #openAssetFileDescriptor(Uri, String)}. You - * will receive a FileNotFoundException exception if the provider returns a - * sub-section of a file. + * interacts with the underlying {@link ContentProvider#openFile} + * ContentProvider.openFile()} method of the provider associated with the + * given URI, to retrieve any file stored there. * * <h5>Accepts the following URI schemes:</h5> * <ul> * <li>content ({@link #SCHEME_CONTENT})</li> - * <li>file ({@link #SCHEME_FILE})</li> * </ul> * - * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information - * on these schemes. - * * @param uri The desired URI to open. * @param mode The file mode to use, as per {@link ContentProvider#openFile * ContentProvider.openFile}. @@ -273,189 +290,32 @@ public abstract class ContentResolver { * own this descriptor and are responsible for closing it when done. * @throws FileNotFoundException Throws FileNotFoundException of no * file exists under the URI or the mode is invalid. - * @see #openAssetFileDescriptor(Uri, String) */ public final ParcelFileDescriptor openFileDescriptor(Uri uri, String mode) throws FileNotFoundException { - AssetFileDescriptor afd = openAssetFileDescriptor(uri, mode); - if (afd == null) { - return null; - } - - if (afd.getDeclaredLength() < 0) { - // This is a full file! - return afd.getParcelFileDescriptor(); + IContentProvider provider = acquireProvider(uri); + if (provider == null) { + throw new FileNotFoundException("No content provider: " + uri); } - - // Client can't handle a sub-section of a file, so close what - // we got and bail with an exception. try { - afd.close(); - } catch (IOException e) { - } - - throw new FileNotFoundException("Not a whole file"); - } - - /** - * Open a raw file descriptor to access data under a "content:" URI. This - * interacts with the underlying {@link ContentProvider#openAssetFile} - * ContentProvider.openAssetFile()} method of the provider associated with the - * given URI, to retrieve any file stored there. - * - * <h5>Accepts the following URI schemes:</h5> - * <ul> - * <li>content ({@link #SCHEME_CONTENT})</li> - * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li> - * <li>file ({@link #SCHEME_FILE})</li> - * </ul> - * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5> - * <p> - * A Uri object can be used to reference a resource in an APK file. The - * Uri should be one of the following formats: - * <ul> - * <li><code>android.resource://package_name/id_number</code><br/> - * <code>package_name</code> is your package name as listed in your AndroidManifest.xml. - * For example <code>com.example.myapp</code><br/> - * <code>id_number</code> is the int form of the ID.<br/> - * The easiest way to construct this form is - * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre> - * </li> - * <li><code>android.resource://package_name/type/name</code><br/> - * <code>package_name</code> is your package name as listed in your AndroidManifest.xml. - * For example <code>com.example.myapp</code><br/> - * <code>type</code> is the string form of the resource type. For example, <code>raw</code> - * or <code>drawable</code>. - * <code>name</code> is the string form of the resource name. That is, whatever the file - * name was in your res directory, without the type extension. - * The easiest way to construct this form is - * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre> - * </li> - * </ul> - * - * @param uri The desired URI to open. - * @param mode The file mode to use, as per {@link ContentProvider#openAssetFile - * ContentProvider.openAssetFile}. - * @return Returns a new ParcelFileDescriptor pointing to the file. You - * own this descriptor and are responsible for closing it when done. - * @throws FileNotFoundException Throws FileNotFoundException of no - * file exists under the URI or the mode is invalid. - */ - public final AssetFileDescriptor openAssetFileDescriptor(Uri uri, - String mode) throws FileNotFoundException { - String scheme = uri.getScheme(); - if (SCHEME_ANDROID_RESOURCE.equals(scheme)) { - if (!"r".equals(mode)) { - throw new FileNotFoundException("Can't write resources: " + uri); - } - OpenResourceIdResult r = getResourceId(uri); - try { - return r.r.openRawResourceFd(r.id); - } catch (Resources.NotFoundException ex) { - throw new FileNotFoundException("Resource does not exist: " + uri); - } - } else if (SCHEME_FILE.equals(scheme)) { - ParcelFileDescriptor pfd = ParcelFileDescriptor.open( - new File(uri.getPath()), modeToMode(uri, mode)); - return new AssetFileDescriptor(pfd, 0, -1); - } else { - IContentProvider provider = acquireProvider(uri); - if (provider == null) { - throw new FileNotFoundException("No content provider: " + uri); - } - try { - AssetFileDescriptor fd = provider.openAssetFile(uri, mode); - if(fd == null) { - releaseProvider(provider); - return null; - } - ParcelFileDescriptor pfd = new ParcelFileDescriptorInner( - fd.getParcelFileDescriptor(), provider); - return new AssetFileDescriptor(pfd, fd.getStartOffset(), - fd.getDeclaredLength()); - } catch (RemoteException e) { - releaseProvider(provider); - throw new FileNotFoundException("Dead content provider: " + uri); - } catch (FileNotFoundException e) { + ParcelFileDescriptor fd = provider.openFile(uri, mode); + if(fd == null) { releaseProvider(provider); - throw e; - } catch (RuntimeException e) { - releaseProvider(provider); - throw e; + return null; } + return new ParcelFileDescriptorInner(fd, provider); + } catch (RemoteException e) { + releaseProvider(provider); + throw new FileNotFoundException("Dead content provider: " + uri); + } catch (FileNotFoundException e) { + releaseProvider(provider); + throw e; + } catch (RuntimeException e) { + releaseProvider(provider); + throw e; } } - class OpenResourceIdResult { - Resources r; - int id; - } - - OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException { - String authority = uri.getAuthority(); - Resources r; - if (TextUtils.isEmpty(authority)) { - throw new FileNotFoundException("No authority: " + uri); - } else { - try { - r = mContext.getPackageManager().getResourcesForApplication(authority); - } catch (NameNotFoundException ex) { - throw new FileNotFoundException("No package found for authority: " + uri); - } - } - List<String> path = uri.getPathSegments(); - if (path == null) { - throw new FileNotFoundException("No path: " + uri); - } - int len = path.size(); - int id; - if (len == 1) { - try { - id = Integer.parseInt(path.get(0)); - } catch (NumberFormatException e) { - throw new FileNotFoundException("Single path segment is not a resource ID: " + uri); - } - } else if (len == 2) { - id = r.getIdentifier(path.get(1), path.get(0), authority); - } else { - throw new FileNotFoundException("More than two path segments: " + uri); - } - if (id == 0) { - throw new FileNotFoundException("No resource found for: " + uri); - } - OpenResourceIdResult res = new OpenResourceIdResult(); - res.r = r; - res.id = id; - return res; - } - - /** @hide */ - static public int modeToMode(Uri uri, String mode) throws FileNotFoundException { - int modeBits; - if ("r".equals(mode)) { - modeBits = ParcelFileDescriptor.MODE_READ_ONLY; - } else if ("w".equals(mode) || "wt".equals(mode)) { - modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY - | ParcelFileDescriptor.MODE_CREATE - | ParcelFileDescriptor.MODE_TRUNCATE; - } else if ("wa".equals(mode)) { - modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY - | ParcelFileDescriptor.MODE_CREATE - | ParcelFileDescriptor.MODE_APPEND; - } else if ("rw".equals(mode)) { - modeBits = ParcelFileDescriptor.MODE_READ_WRITE - | ParcelFileDescriptor.MODE_CREATE; - } else if ("rwt".equals(mode)) { - modeBits = ParcelFileDescriptor.MODE_READ_WRITE - | ParcelFileDescriptor.MODE_CREATE - | ParcelFileDescriptor.MODE_TRUNCATE; - } else { - throw new FileNotFoundException("Bad mode for " + uri + ": " - + mode); - } - return modeBits; - } - /** * Inserts a row into a table at the given URL. * |