이미지 키보드 지원

사용자는 이모티콘, 스티커 등 풍부한 정보를 사용하여 소통하고 싶어 하는 경우가 많습니다. 있습니다. 이전 버전의 Android에서는 소프트 키보드(또는 입력 방식 편집기(IME) 또는 IME—유니코드 그림 이모티콘만 앱에 보낼 수 있음 풍부한 콘텐츠를 위한 앱 다른 앱에서 사용할 수 없거나 간단한 공유 작업을 통해 이미지 전송 클립보드로 이동할 수 있습니다.

이미지 검색을 지원하는 키보드를 보여주는 이미지
그림 1. 이미지 키보드 지원의 예

Android 7.1 (API 수준 25)부터 Android SDK에 커밋이 포함되어 있습니다. Content API: IME가 이미지 및 기타 멀티미디어 콘텐츠를 전송하는 보편적인 방법을 앱의 텍스트 편집기에 직접 전달할 수 있습니다. API는 다음에서도 사용할 수 있습니다. 버전 25.0.0부터 v13 지원 라이브러리만 지원합니다. 지원팀을 사용하는 것이 좋습니다. 구현을 간소화하는 도우미 메서드가 포함되어 있으므로 라이브러리입니다.

이 API를 사용하면 모든 애플리케이션에서 리치 콘텐츠를 허용하는 메시지 앱을 빌드할 수 있습니다. 앱에 리치 콘텐츠를 보낼 수 있는 키보드도 포함됩니다. Google 키보드 메시지 Google 그림 1과 같이 Android 7.1에서 Commit Content API를 지원해야 합니다.

이 문서에서는 IME 및 있습니다.

작동 방식

키보드 이미지 삽입을 사용하려면 IME 및 앱의 참여가 필요합니다. 이 다음 시퀀스는 이미지 삽입 프로세스의 각 단계를 설명합니다.

  1. 사용자가 EditText를 탭하면 편집기가 EditorInfo.contentMimeTypes

  2. IME는 지원되는 유형 목록을 읽고 편집기가 허용할 수 있는 소프트 키보드의 콘텐츠를 표시합니다.

  3. 사용자가 이미지를 선택하면 IME가 commitContent() 드림 를 전송하며 InputContentInfo 수정하겠습니다 commitContent() 호출은 commitText() 호출은 리치 콘텐츠를 사용할 수 있습니다. InputContentInfo에는 다음과 같은 URI가 포함됩니다. 콘텐츠에서 콘텐츠를 식별하는 provider로 이동합니다.

이 프로세스는 그림 2에 묘사되어 있습니다.

애플리케이션에서 IME로, 다시 애플리케이션으로 이어지는 시퀀스를 보여주는 이미지
그림 2. 애플리케이션에서 IME로의 애플리케이션 흐름

앱에 이미지 지원 추가

IME의 리치 콘텐츠를 허용하려면 앱에서 콘텐츠 유형을 IME에 알려야 합니다. 콘텐츠를 수신할 때 실행되는 콜백 메서드를 수락하고 지정합니다. 다음 예는 PNG를 허용하는 EditText를 만드는 방법을 보여줍니다. 이미지:

Kotlin

var editText: EditText = object : EditText(this) {
    override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
        var ic = super.onCreateInputConnection(outAttrs)
        EditorInfoCompat.setContentMimeTypes(outAttrs, arrayOf("image/png"))
        val mimeTypes = ViewCompat.getOnReceiveContentMimeTypes(this)
        if (mimeTypes != null) {
            EditorInfoCompat.setContentMimeTypes(outAttrs, mimeTypes)
            ic = InputConnectionCompat.createWrapper(this, ic, outAttrs)
        }
        return ic
    }
}

자바

EditText editText = new EditText(this) {
    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        InputConnection ic = super.onCreateInputConnection(outAttrs);
        EditorInfoCompat.setContentMimeTypes(outAttrs, new String[]{"image/png"});
        String[] mimeTypes = ViewCompat.getOnReceiveContentMimeTypes(this);
        if (mimeTypes != null) {
            EditorInfoCompat.setContentMimeTypes(outAttrs, mimeTypes);
            ic = InputConnectionCompat.createWrapper(this, ic, outAttrs);
        }
        return ic;
    }
};

자세한 설명은 다음과 같습니다.

권장사항은 다음과 같습니다.

  • 리치 콘텐츠를 지원하지 않는 편집자는 호출하지 않습니다. setContentMimeTypes()이며 EditorInfo.contentMimeTypes 세트를 그대로 둡니다. null님에게 보냅니다.

  • InputContentInfo에 지정된 MIME 유형이 있으면 편집자가 콘텐츠를 무시합니다. 허용되는 유형과 일치하지 않습니다.

  • 리치 콘텐츠는 텍스트 위치에 영향을 주지 않으며 영향을 받지도 않습니다. 커서를 올려놓습니다. 편집기는 콘텐츠를 사용할 때 커서 위치를 무시할 수 있습니다.

  • 편집기의 OnCommitContentListener.onCommitContent() 메서드를 사용하여 비동기식으로 true를 반환할 수도 있고 콘텐츠를 로드하기 전에 확인할 수 있습니다

  • 커밋되기 전에 IME에서 수정할 수 있는 텍스트와 달리 풍부한 커밋 즉시 커밋됩니다. 사용자가 파일을 수정하거나 삭제할 수 있게 하려는 경우 로직을 직접 구현해야 합니다.

앱을 테스트하려면 기기나 에뮬레이터에 키보드가 내장되어 있어야 합니다. 있습니다. Android 7.1 이상에서 Google 키보드를 사용할 수 있습니다.

IME에 이미지 지원 추가

앱에 리치 콘텐츠를 전송하려는 IME는 커밋 콘텐츠를 구현해야 합니다. API를 사용할 수 있습니다.

  • 재정의 onStartInput() 또는 onStartInputView()하고 타겟에서 지원되는 콘텐츠 유형 목록을 읽습니다. 있습니다 다음 코드 스니펫은 타겟 편집기에서 GIF 이미지를 허용하는지 확인하는 방법을 보여줍니다.

Kotlin

override fun onStartInputView(editorInfo: EditorInfo, restarting: Boolean) {
    val mimeTypes: Array<String> = EditorInfoCompat.getContentMimeTypes(editorInfo)

    val gifSupported: Boolean = mimeTypes.any {
        ClipDescription.compareMimeTypes(it, "image/gif")
    }

    if (gifSupported) {
        // The target editor supports GIFs. Enable the corresponding content.
    } else {
        // The target editor doesn't support GIFs. Disable the corresponding
        // content.
    }
}

자바

@Override
public void onStartInputView(EditorInfo info, boolean restarting) {
    String[] mimeTypes = EditorInfoCompat.getContentMimeTypes(editorInfo);

    boolean gifSupported = false;
    for (String mimeType : mimeTypes) {
        if (ClipDescription.compareMimeTypes(mimeType, "image/gif")) {
            gifSupported = true;
        }
    }

    if (gifSupported) {
        // The target editor supports GIFs. Enable the corresponding content.
    } else {
        // The target editor doesn't support GIFs. Disable the corresponding
        // content.
    }
}
  • 사용자가 이미지를 선택하면 앱에 콘텐츠를 커밋합니다. 통화 지양 commitContent() 작성 중인 텍스트가 있는 경우 편집기가 포커스를 잃을 수 있습니다. 다음 코드 스니펫은 GIF 이미지를 커밋할 수 있습니다.

Kotlin

// Commits a GIF image.

// @param contentUri = Content URI of the GIF image to be sent.
// @param imageDescription = Description of the GIF image to be sent.

fun commitGifImage(contentUri: Uri, imageDescription: String) {
    val inputContentInfo = InputContentInfoCompat(
            contentUri,
            ClipDescription(imageDescription, arrayOf("image/gif")),
            null
    )
    val inputConnection = currentInputConnection
    val editorInfo = currentInputEditorInfo
    var flags = 0
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
        flags = flags or InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION
    }
    InputConnectionCompat.commitContent(inputConnection, editorInfo, inputContentInfo, flags, null)
}

자바

// Commits a GIF image.

// @param contentUri = Content URI of the GIF image to be sent.
// @param imageDescription = Description of the GIF image to be sent.

public static void commitGifImage(Uri contentUri, String imageDescription) {
    InputContentInfoCompat inputContentInfo = new InputContentInfoCompat(
            contentUri,
            new ClipDescription(imageDescription, new String[]{"image/gif"}),
            null
    );
    InputConnection inputConnection = getCurrentInputConnection();
    EditorInfo editorInfo = getCurrentInputEditorInfo();
    Int flags = 0;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
        flags |= InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION;
    }
    InputConnectionCompat.commitContent(
            inputConnection, editorInfo, inputContentInfo, flags, null);
}

IME 작성자로서 개발자는 자체 콘텐츠 제공자를 구현하여 콘텐츠 URI 요청에 응답합니다. IME가 콘텐츠를 지원하는 경우는 예외입니다. 기존 콘텐츠 제공업체로부터 MediaStore 자세한 내용은 자세한 내용은 providerfile provider 문서를 참조하세요.

자체 콘텐츠 제공업체를 빌드하는 경우 내보내지 않는 것이 좋습니다. 설정 android:exported(으)로 false입니다. 대신 다음을 설정하여 제공자의 권한 부여를 사용 설정하세요. android:grantUriPermission 드림 true에게. 그러면 콘텐츠가 커밋될 때 IME에서 콘텐츠 URI 액세스 권한을 부여할 수 있습니다. 다음과 같은 두 가지 방법이 있습니다.

  • Android 7.1 (API 수준 25) 이상에서 commitContent() 호출 시 플래그 매개변수를 INPUT_CONTENT_GRANT_READ_URI_PERMISSION 그러면 앱이 수신하는 InputContentInfo 객체가 요청 및 다음을 호출하여 임시 읽기 권한을 해제합니다. requestPermission()releasePermission()입니다.

  • Android 7.0 (API 수준 24) 이하에서는 INPUT_CONTENT_GRANT_READ_URI_PERMISSION가 무시되므로 수동으로 부여합니다. 콘텐츠에 대한 권한을 부여하지 않습니다. 이를 위한 한 가지 방법은 grantUriPermission()를 지원하지만 개발자가 직접 실행할 내 요구사항에 맞게 맞춤설정할 수 있습니다

IME를 테스트하려면 기기나 에뮬레이터에 있습니다. Google 메신저 앱은 Android 7.1 이상에서 사용할 수 있습니다.