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 * @Override 37 * public ContentInfo onReceiveContent(View view, ContentInfo payload) { 38 * Pair<ContentInfo, ContentInfo> split = 39 * ContentInfoCompat.partition(payload, item -> 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 * @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