• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 
22 /**
23  * Listener for apps to implement handling for insertion of content. Content may be both text and
24  * non-text (plain/styled text, HTML, images, videos, audio files, etc).
25  *
26  * <p>This listener can be attached to different types of UI components using
27  * {@link View#setOnReceiveContentListener}.
28  *
29  * <p>Here is a sample implementation that handles content URIs and delegates the processing for
30  * text and everything else to the platform:<br>
31  * <pre class="prettyprint">
32  * // (1) Define the listener
33  * public class MyReceiver implements OnReceiveContentListener {
34  *     public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"};
35  *
36  *     &#64;Override
37  *     public ContentInfo onReceiveContent(View view, ContentInfo payload) {
38  *         Pair&lt;ContentInfo, ContentInfo&gt; split =
39  *                 ContentInfoCompat.partition(payload, item -&gt; item.getUri() != null);
40  *         ContentInfo uriContent = split.first;
41  *         ContentInfo remaining = split.second;
42  *         if (uriContent != null) {
43  *             ClipData clip = uriContent.getClip();
44  *             for (int i = 0; i < clip.getItemCount(); i++) {
45  *                 Uri uri = clip.getItemAt(i).getUri();
46  *                 // ... app-specific logic to handle the URI ...
47  *             }
48  *         }
49  *         // Return anything that we didn't handle ourselves. This preserves the default platform
50  *         // behavior for text and anything else for which we are not implementing custom handling.
51  *         return remaining;
52  *     }
53  * }
54  *
55  * // (2) Register the listener
56  * public class MyActivity extends Activity {
57  *     &#64;Override
58  *     public void onCreate(Bundle savedInstanceState) {
59  *         // ...
60  *
61  *         EditText myInput = findViewById(R.id.my_input);
62  *         myInput.setOnReceiveContentListener(MyReceiver.MIME_TYPES, new MyReceiver());
63  *     }
64  * </pre>
65  */
66 public interface OnReceiveContentListener {
67     /**
68      * Receive the given content.
69      *
70      * <p>Implementations should handle any content items of interest and return all unhandled
71      * items to preserve the default platform behavior for content that does not have app-specific
72      * handling. For example, an implementation may provide handling for content URIs (to provide
73      * support for inserting images, etc) and delegate the processing of text to the platform to
74      * preserve the common behavior for inserting text. See the class javadoc for a sample
75      * implementation.
76      *
77      * <h3>Handling different content</h3>
78      * <ul>
79      *     <li>Text. If the {@link ContentInfo#getSource() source} is
80      *     {@link ContentInfo#SOURCE_AUTOFILL autofill}, the view's content should be fully
81      *     replaced by the passed-in text. For sources other than autofill, the passed-in text
82      *     should overwrite the current selection or be inserted at the current cursor position
83      *     if there is no selection.
84      *     <li>Non-text content (e.g. images). The content may be inserted inline if the widget
85      *     supports this, or it may be added as an attachment (could potentially be shown in a
86      *     completely separate view).
87      * </ul>
88      *
89      * <h3>URI permissions</h3>
90      * <p>{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION Read permissions} are
91      * granted automatically by the platform for any
92      * {@link android.content.ContentResolver#SCHEME_CONTENT content URIs} in the payload passed
93      * to this listener. Permissions are transient and will be released automatically by the
94      * platform.
95      * <p>Processing of content should normally be done in a service or activity.
96      * For long-running processing, using {@code androidx.work.WorkManager} is recommended.
97      * When implementing this, permissions should be extended to the target service or activity
98      * by passing the content using {@link android.content.Intent#setClipData Intent.setClipData}
99      * and {@link android.content.Intent#addFlags(int) setting} the flag
100      * {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION FLAG_GRANT_READ_URI_PERMISSION}.
101      * <p>Alternatively, if using a background thread within the current context to process the
102      * content, a reference to the {@code payload} object should be maintained to ensure that
103      * permissions are not revoked prematurely.
104      *
105      * @param view The view where the content insertion was requested.
106      * @param payload The content to insert and related metadata. The payload may contain multiple
107      *                items and their MIME types may be different (e.g. an image item and a text
108      *                item). The payload may also contain items whose MIME type is not in the list
109      *                of MIME types specified when
110      *                {@link View#setOnReceiveContentListener setting} the listener. For
111      *                those items, the listener may reject the content (defer to the default
112      *                platform behavior) or execute some other fallback logic (e.g. show an
113      *                appropriate message to the user).
114      *
115      * @return The portion of the passed-in content whose processing should be delegated to
116      * the platform. Return null if all content was handled in some way. Actual insertion of
117      * the content may be processed asynchronously in the background and may or may not
118      * succeed even if this method returns null. For example, an app may end up not inserting
119      * an item if it exceeds the app's size limit for that type of content.
120      */
121     @Nullable
onReceiveContent(@onNull View view, @NonNull ContentInfo payload)122     ContentInfo onReceiveContent(@NonNull View view, @NonNull ContentInfo payload);
123 }
124