Merge "Add Web Links API to framework."

This commit is contained in:
Tomasz Mikolajewski
2017-01-19 05:26:07 +00:00
committed by Android (Google) Code Review
5 changed files with 142 additions and 0 deletions

View File

@@ -28,6 +28,7 @@ import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ResolveInfo;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
@@ -421,6 +422,14 @@ public final class DocumentsContract {
*/
public static final int FLAG_SUPPORTS_SETTINGS = 1 << 11;
/**
* Flag indicating that a Web link can be obtained for the document.
*
* @see #COLUMN_FLAGS
* @see DocumentsContract#createWebLinkIntent(PackageManager, Uri, Bundle)
*/
public static final int FLAG_WEB_LINKABLE = 1 << 12;
/**
* Flag indicating that a document is not complete, likely its
* contents are being downloaded. Partial files cannot be opened,
@@ -685,12 +694,20 @@ public final class DocumentsContract {
public static final String METHOD_EJECT_ROOT = "android:ejectRoot";
/** {@hide} */
public static final String METHOD_FIND_DOCUMENT_PATH = "android:findDocumentPath";
/** {@hide} */
public static final String METHOD_CREATE_WEB_LINK_INTENT = "android:createWebLinkIntent";
/** {@hide} */
public static final String EXTRA_PARENT_URI = "parentUri";
/** {@hide} */
public static final String EXTRA_URI = "uri";
/**
* @see #createWebLinkIntent(ContentResolver, Uri, Bundle)
* {@hide}
*/
public static final String EXTRA_OPTIONS = "options";
private static final String PATH_ROOT = "root";
private static final String PATH_RECENT = "recent";
private static final String PATH_DOCUMENT = "document";
@@ -1400,6 +1417,85 @@ public final class DocumentsContract {
return out.getParcelable(DocumentsContract.EXTRA_RESULT);
}
/**
* Creates an intent for obtaining a web link for the specified document.
*
* <p>Note, that due to internal limitations, if there is already a web link
* intent created for the specified document but with different options,
* then it may be overriden.
*
* <p>Providers are required to show confirmation UI for all new permissions granted
* for the linked document.
*
* <p>If list of recipients is known, then it should be passed in options as
* {@link Intent#EXTRA_EMAIL} as either a string or list of strings. Note, that
* this is just a hint for the provider, which can ignore the list. In either
* case the provider is required to show a UI for letting the user confirm
* any new permission grants.
*
* <p>Since this API may show a UI, it cannot be called from background.
*
* <p>In order to obtain the Web Link use code like this:
* <pre><code>
* void onSomethingHappened() {
* IntentSender sender = DocumentsContract.createWebLinkIntent(<i>...</i>);
* if (sender != null) {
* startIntentSenderForResult(
* DocumentsContract.createWebLinkIntent(<i>...</i>),
* WEB_LINK_REQUEST_CODE,
* null, 0, 0, 0, null);
* }
* }
*
* <i>(...)</i>
*
* void onActivityResult(int requestCode, int resultCode, Intent data) {
* if (requestCode == WEB_LINK_REQUEST_CODE && resultCode == RESULT_OK) {
* Uri weblinkUri = data.getData();
* <i>...</i>
* }
* }
* </code></pre>
*
* @param uri uri for the document to create a link to.
* @param options Extra information for generating the link.
* @return an intent sender to obtain the web link, or null if the document
* is not linkable, or creating the intent sender failed.
* @see DocumentsProvider#createWebLinkIntent(String, Bundle)
* @see Intent#EXTRA_EMAIL
*/
public static IntentSender createWebLinkIntent(ContentResolver resolver, Uri uri,
Bundle options) {
final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
uri.getAuthority());
try {
return createWebLinkIntent(client, uri, options);
} catch (Exception e) {
Log.w(TAG, "Failed to create a web link intent", e);
return null;
} finally {
ContentProviderClient.releaseQuietly(client);
}
}
/**
* {@hide}
*/
public static IntentSender createWebLinkIntent(ContentProviderClient client, Uri uri,
Bundle options) throws RemoteException {
final Bundle in = new Bundle();
in.putParcelable(DocumentsContract.EXTRA_URI, uri);
// Options may be provider specific, so put them in a separate bundle to
// avoid overriding the Uri.
if (options != null) {
in.putBundle(EXTRA_OPTIONS, options);
}
final Bundle out = client.call(METHOD_CREATE_WEB_LINK_INTENT, null, in);
return out.getParcelable(DocumentsContract.EXTRA_RESULT);
}
/**
* Open the given image for thumbnail purposes, using any embedded EXIF
* thumbnail if available, and providing orientation hints from the parent

View File

@@ -18,6 +18,7 @@ package android.provider;
import static android.provider.DocumentsContract.METHOD_COPY_DOCUMENT;
import static android.provider.DocumentsContract.METHOD_CREATE_DOCUMENT;
import static android.provider.DocumentsContract.METHOD_CREATE_WEB_LINK_INTENT;
import static android.provider.DocumentsContract.METHOD_DELETE_DOCUMENT;
import static android.provider.DocumentsContract.METHOD_EJECT_ROOT;
import static android.provider.DocumentsContract.METHOD_FIND_DOCUMENT_PATH;
@@ -43,6 +44,7 @@ import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.UriMatcher;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
@@ -362,6 +364,33 @@ public abstract class DocumentsProvider extends ContentProvider {
throw new UnsupportedOperationException("findDocumentPath not supported.");
}
/**
* Creates an intent sender for a web link, if the document is web linkable.
* <p>
* Before any new permissions are granted for the linked document, a visible
* UI must be shown, so the user can explicitly confirm whether the permission
* grants are expected. The user must be able to cancel the operation.
* <p>
* Options passed as an argument may include a list of recipients, such
* as email addresses. The provider should reflect these options if possible,
* but it's acceptable to ignore them. In either case, confirmation UI must
* be shown before any new permission grants are granted.
* <p>
* It is all right to generate a web link without granting new permissions,
* if opening the link would result in a page for requesting permission
* access. If it's impossible then the operation must fail by throwing an exception.
*
* @param documentId the document to create a web link intent for.
* @param options additional information, such as list of recipients. Optional.
*
* @see DocumentsContract.Document#FLAG_WEB_LINKABLE
* @see android.app.PendingIntent#getIntentSender
*/
public IntentSender createWebLinkIntent(String documentId, @Nullable Bundle options)
throws FileNotFoundException {
throw new UnsupportedOperationException("createWebLink is not supported.");
}
/**
* Return all roots currently provided. To display to users, you must define
* at least one root. You should avoid making network requests to keep this
@@ -900,6 +929,14 @@ public abstract class DocumentsProvider extends ContentProvider {
newDocumentId);
out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
} else if (METHOD_CREATE_WEB_LINK_INTENT.equals(method)) {
enforceWritePermissionInner(documentUri, getCallingPackage(), null);
final Bundle options = extras.getBundle(DocumentsContract.EXTRA_OPTIONS);
final IntentSender intentSender = createWebLinkIntent(documentId, options);
out.putParcelable(DocumentsContract.EXTRA_RESULT, intentSender);
} else if (METHOD_RENAME_DOCUMENT.equals(method)) {
enforceWritePermissionInner(documentUri, getCallingPackage(), null);