안드로이드 복사 붙여넣기 오류 - andeuloideu bogsa but-yeoneohgi olyu

   파일을 하나의 기기에서 다른 기기로 이동한다는 것은 아주 단순한 행위이다. 하지만 OS가 다르고 하드웨어 환경이 다른 경우 이를 하는 것은 여러가지 난제들이 있는 경우가 있다. 

   물론 일반적인 경우에 길지 않은 파일이름에, 표준화된 파일 포맷에 용량에 한계가 없는 작은 파일에 대해서는 전혀 문제가 없다. 하지만 이종 OS에 하드웨어가 다른 데다가 파일 복사에 문제가 생기는 경우는 무엇이 문제인지 알 수가 없다. 

나의 하드웨어 및 소프트웨어 환경

   갤럭시폴드(SM-F907N)를 사용하고 있다. 

   물론 갤럭시의 안드로이드 OS를 사용하고 있다가 다 맞는 말일지 모르겠다. 

   현재 UI버전 : One UI version 2.1

   안드로이드 OS버전 : 10

   안드로이드의 파일복사는 아주 간단하다 Lock을 풀고, USB케이블을 연결후 원하는 폴더에 카피를 하면 된다. 그런데 안되는 경우가 있다. 

현상 : 

   드래그 앤 드롭으로 1기가 이하의 파일 카피 오류발생, 

   잠시 진행 창이 떠서 용량을 계산하는 듯 하다가 갑자기 사라짐

   오류메시지 없음. 

   몇몇 파일은 카피됨. 하지만 원하는 파일은 600메가 정도 되는 데 복사 실패 

정설 : 안드로이드 OS를 사용하니 구글의 도움말 따라하기

컴퓨터와 Android 기기 간 파일 전송 - Android 고객센터

도움이 되었나요? 어떻게 하면 개선할 수 있을까요? 예아니요

support.google.com

개발자모드 사용하기 : 

삼성 갤럭시 스마트폰 파일 또는 폴더 복사 오류 문제점 해결방법

얼마 전부터 갤럭시 스마트폰으로 찍은 사진을 노트북으로 옮길려고 할때마다 아래와 같이 잘못된 종류의 데이터가 제공되었습니다라는 창이 뜨면서 파일 또는 폴더 복사 오류가 발생해서 불��

withbbang.tistory.com

안드로이드 복사 붙여넣기 오류 - andeuloideu bogsa but-yeoneohgi olyu

   이 해결방안을 써도 해결이 되지 않았다. 

마이크로소프트 제공 소프트웨어 설치

   회원가입이 필요하다. 비추 언제 가입하냐? 될지 안될지도 모르는데...

갤럭시노트10 윈도우10 '사용자 휴대폰 연결'의 진실?

​요즘 정말 연일 뜨거운 이슈가 끊이지 않고 있죠. 처음으로 플러스 모델이 추가되었고 아주 슬림한 시네...

blog.naver.com

안드로이드 복사 붙여넣기 오류 - andeuloideu bogsa but-yeoneohgi olyu

삼성 Kies의 사용

삼성 Kies - 나무위키

이 저작물은 CC BY-NC-SA 2.0 KR에 따라 이용할 수 있습니다. (단, 라이선스가 명시된 일부 문서 및 삽화 제외) 기여하신 문서의 저작권은 각 기여자에게 있으며, 각 기여자는 기여하신 부분의 저작권�

namu.wiki

안드로이드 복사 붙여넣기 오류 - andeuloideu bogsa but-yeoneohgi olyu

   오류투성이라 비추

여러가지 가능성 

   파일 자체의 문제일 가능성 : 하지만 잘 동작되었다. 

   파일의 바이러스 감염 : 하지만 내 PC엔 바이러스 감염 방지 프로그램도 깔려 있다.

   스마트폰 플래쉬 메모리 용량 점검 : 수십 Giga가 남아 있었지만, 그래도 혹시나 숨겨진 파일 때문에 차단이 되나 싶어서 다른 파일을 넣었다. 잘 플레이가 되고 또 재생도 된다.

   함께 Copy하는 다른 파일 : 몇개는 재생이 되고 특정 폴더만 통째로 안된다.

   KNOX(삼성핸드폰) 이 방화벽을 치고 이상한 파일은 차단시키는 가 : 그래서 압축파일은 점검을 안하리라 생각하고 카피를 했다. 하지만 압축파일은 풀려면 스마트폰에 압축해제 프로그램을 설치하고 풀어야 한다. 아 복잡하다. 포기.

파일 이름 길이의 문제

   길이나 특수문자가 있는 경우 인식을 못하는 경우들이 있다. Windows10에서 Office파일이 열리지 않았단다. Office는 윈도우에서도 전적으로 밀고 있는 소프트웨어 그렇다면 같은 문제일 수 있다.

폴더 이름이 긴 Office 파일을 열 수 없음

폴더 이름이 긴 Office 파일을 열면 오류 메시지가 표시 될 수 있는 문제에 대해 설명 합니다.

docs.microsoft.com

안드로이드 복사 붙여넣기 오류 - andeuloideu bogsa but-yeoneohgi olyu

   반면, 안드로이드의 파일명 길이는 이론적으로 제약은 없지만 128자까지는 안전하게 지원한다고 한다. 

[Xamarin] iOS, Android 파일명

Android 전체경로 길이: 1150자 Java는 파일명 길이제한에 대한 기준이 없습니다. Java 프로그램이 실행되는 운영체제, 제조사, FileSystem에 따라 달라질 수 있다고 합니다. 테스트에 따르면 Android에서 ��

points.tistory.com

안드로이드 복사 붙여넣기 오류 - andeuloideu bogsa but-yeoneohgi olyu

    2019년 7월 즈음에 까지도 탐색기에서 파일이름을 바꾸지 못하는 문제가 생겼다고 한다. 

지정한 파일 이름이 올바르지 않거나 너무 깁니다. 오류 해결 방법 (윈도우 탐색기 글자 수 제한)

문제 상황PC에 존재하는 긴 이름을 가진 파일/폴더를 삭제하거나 이름을 바꾸지 못하는 상황원인윈도우 ...

blog.naver.com

안드로이드 복사 붙여넣기 오류 - andeuloideu bogsa but-yeoneohgi olyu

   유추해서 안드로이드OS가 이런걸 잘 받아주지 못할 수 있다는 추론을 완성했다. 그래고는 80자에 가까운 길이를 10자가까이 확줄여 버렸다. 그리고 copy시도

성공

Android는 복사하여 붙여넣기를 지원하는 강력한 클립보드 기반 프레임워크를 제공합니다. 텍스트 문자열, 복잡한 데이터 구조, 텍스트 및 바이너리 스트림 데이터, 애플리케이션 애셋을 포함하여 단순한 데이터 유형과 복잡한 데이터 유형을 모두 지원합니다. 단순한 텍스트 데이터는 클립보드에 직접 저장되며 복잡한 데이터는 붙여넣기 애플리케이션이 콘텐츠 제공업체를 통해 확인하는 참조로 저장됩니다. 하나의 애플리케이션 내에서뿐 아니라 프레임워크를 구현하는 여러 애플리케이션 사이에서 모두 복사하여 붙여넣기를 할 수 있습니다.

프레임워크의 일부에서 콘텐츠 제공자를 사용하므로 이 주제에서는 콘텐츠 제공자 주제에서 설명된 Android Content Provider API를 어느 정도 알고 있다고 가정합니다.

클립보드 프레임워크

클립보드 프레임워크를 사용할 때 데이터를 클립 객체에 넣은 다음 클립 객체를 시스템 전체 클립보드에 배치합니다. 클립 객체는 다음 세 가지 형식 중 하나일 수 있습니다.

텍스트텍스트 문자열입니다. 문자열을 클립 객체에 직접 넣은 다음 클립보드에 배치합니다. 문자열을 붙여넣으려면 클립보드에서 클립 객체를 가져와서 문자열을 애플리케이션의 저장소에 복사합니다. URI모든 URI 형식을 표시하는 Uri 객체입니다. 주로 콘텐츠 제공업체의 복잡한 데이터를 복사하기 위한 것입니다. 데이터를 복사하려면 Uri 객체를 클립 객체에 넣고 클립 객체를 클립보드에 배치합니다. 데이터를 붙여넣으려면 클립 객체와 Uri 객체를 가져와서 콘텐츠 제공업체와 같은 데이터 소스로 확인하고 소스에서 애플리케이션의 저장소로 데이터를 복사합니다. 인텐트Intent입니다. 애플리케이션 바로가기 복사를 지원합니다. 데이터를 복사하려면 인텐트를 만들고 클립 객체에 넣은 다음 클립 객체를 클립보드에 배치합니다. 데이터를 붙여넣으려면 클립 객체를 가져온 다음 인텐트 객체를 애플리케이션의 메모리 영역으로 복사합니다.

클립보드는 한 번에 클립 객체 하나만 보유합니다. 애플리케이션에서 클립 객체를 클립보드에 배치하면 이전 클립 객체는 사라집니다.

사용자가 애플리케이션에 데이터를 붙여넣도록 허용하려면 모든 데이터 유형을 처리할 필요가 없습니다. 클립보드의 데이터를 검사한 후 사용자에게 붙여넣기 옵션을 제공할 수 있습니다. 클립 객체에는 특정 데이터 형식 외에도 사용 가능한 MIME 유형을 알려주는 메타데이터도 포함됩니다. 메타데이터를 통해 애플리케이션이 클립보드 데이터로 유용한 작업을 실행할 수 있는지 판단할 수 있습니다. 예를 들어 텍스트를 주로 처리하는 애플리케이션이 있다면 URI 또는 인텐트가 포함된 클립 객체를 무시하는 것이 좋습니다.

사용자가 클립보드의 데이터 형식에 상관없이 텍스트를 붙여넣도록 하는 것도 좋습니다. 이렇게 하려면 클립보드 데이터를 텍스트 표현으로 강제 변환한 다음 이 텍스트를 붙여넣으면 됩니다. 이 방법은 클립보드를 텍스트로 강제 변환 섹션에 설명되어 있습니다.

클립보드 클래스

이 섹션에서는 클립보드 프레임워크에서 사용하는 클래스를 설명합니다.

ClipboardManager

Android 시스템에서 시스템 클립보드는 전역 ClipboardManager 클래스로 표시됩니다. 이 클래스를 직접 인스턴스화하지 마세요. 대신 getSystemService(CLIPBOARD_SERVICE)를 호출하여 클래스 참조를 가져옵니다.

ClipData, ClipData.Item, ClipDescription

데이터를 클립보드에 추가하려면 데이터 설명과 데이터 자체를 모두 포함하는 ClipData 객체를 만드세요. 클립보드는 한 번에 ClipData 하나만 보유합니다. ClipData에는 ClipDescription 객체와 하나 이상의 ClipData.Item 객체가 포함됩니다.

ClipDescription 객체에는 클립에 관한 메타데이터가 포함됩니다. 특히 클립 데이터에 사용할 수 있는 MIME 유형의 배열이 포함됩니다. 클립보드에 클립을 배치하면 이 배열을 붙여넣기 애플리케이션에서 사용할 수 있습니다. 붙여넣기 애플리케이션은 이 배열을 검사하여 사용 가능한 MIME 유형을 처리할 수 있는지 확인할 수 있습니다.

ClipData.Item 객체에는 텍스트, URI 또는 인텐트 데이터가 포함됩니다.

텍스트CharSequence입니다.URIUri입니다. 모든 URI가 허용되지만 일반적으로 콘텐츠 제공업체 URI가 포함됩니다. 데이터를 제공하는 애플리케이션은 URI를 클립보드에 배치합니다. 데이터를 붙여넣으려는 애플리케이션은 클립보드에서 URI를 가져와서 콘텐츠 제공업체(또는 다른 데이터 소스)에 액세스하여 데이터를 검색하는 데 사용합니다. 인텐트Intent입니다. 이 데이터 유형을 사용하면 애플리케이션 바로가기를 클립보드에 복사할 수 있습니다. 그러면 사용자가 바로가기를 애플리케이션에 붙여넣어 나중에 사용할 수 있습니다.

클립에 ClipData.Item 객체를 두 개 이상 추가할 수 있습니다. 이렇게 하면 사용자가 여러 선택사항을 단일 클립으로 복사하여 붙여넣기 할 수 있습니다. 예를 들어 사용자가 항목을 한 번에 두 개 이상 선택할 수 있는 목록 위젯이 있다면 클립보드에 모든 항목을 한 번에 복사할 수 있습니다. 이 작업을 실행하려면 각 목록 항목에 별도의 ClipData.Item을 만든 다음 ClipData.Item 객체를 ClipData 객체에 추가합니다.

ClipData 편의 메서드

ClipData 클래스는 단일 ClipData.Item 객체 및 단순한 ClipDescription 객체를 사용하여 ClipData 객체를 만들기 위한 정적 편의 메서드를 제공합니다.

newPlainText(label, text)단일 ClipData.Item 객체에 텍스트 문자열이 포함되는 ClipData 객체를 반환합니다. ClipDescription 객체의 라벨이 label로 설정됩니다. ClipDescription의 단일 MIME 유형은 MIMETYPE_TEXT_PLAIN입니다.

newPlainText()를 사용하여 텍스트 문자열에서 클립을 만드세요.

newUri(resolver, label, URI)단일 ClipData.Item 객체에 URI가 포함되는 ClipData 객체를 반환합니다. ClipDescription 객체의 라벨이 label로 설정됩니다. URI가 콘텐츠 URI(Uri.getScheme()content: 반환)면 메서드는 resolver에서 제공한 ContentResolver 객체를 사용하여 콘텐츠 제공업체에서 사용 가능한 MIME 유형을 검색하고 ClipDescription에 저장합니다. content: URI가 아닌 URI의 경우 메서드는 MIME 유형을 MIMETYPE_TEXT_URILIST로 설정합니다.

newUri()를 사용하여 URI, 특히 content: URI에서 클립을 만드세요.

newIntent(label, intent) 단일 ClipData.Item 객체에 Intent가 포함되는 ClipData 객체를 반환합니다. ClipDescription 객체의 라벨이 label로 설정됩니다. MIME 유형이 MIMETYPE_TEXT_INTENT로 설정됩니다.

newIntent()를 사용하여 인텐트 객체에서 클립을 만드세요.

클립보드 데이터를 텍스트로 강제 변환

애플리케이션에서 텍스트만 처리한다고 해도 텍스트가 아닌 데이터를 메서드 ClipData.Item.coerceToText()로 변환하여 클립보드에서 복사할 수 있습니다.

이 메서드는 ClipData.Item의 데이터를 텍스트로 변환하여 CharSequence를 반환합니다. ClipData.Item.coerceToText()가 반환하는 값은 ClipData.Item의 데이터 형식에 기반합니다.

텍스트ClipData.Item이 텍스트(getText()는 null이 아님)인 경우 coerceToText()는 텍스트를 반환합니다.URIClipData.Item이 URI(getUri()는 null이 아님)인 경우 coerceToText()가 콘텐츠 URI로 사용하려고 합니다.
  • URI가 콘텐츠 URI이고 제공업체가 텍스트 스트림을 반환할 수 있다면 coerceToText()는 텍스트 스트림을 반환합니다.
  • URI가 콘텐츠 URI이지만 제공업체가 텍스트 스트림을 제공하지 않는다면 coerceToText()는 URI 표시를 반환합니다. 표시는 Uri.toString()에서 반환한 것과 동일합니다.
  • URI가 콘텐츠 URI가 아니라면 coerceToText()는 URI 표시를 반환합니다. 표시는 Uri.toString()에서 반환한 것과 동일합니다.
인텐트ClipData.Item이 인텐트(getIntent()는 null이 아님)인 경우 coerceToText()는 인텐트 URI로 변환하여 반환합니다. 표시는 Intent.toUri(URI_INTENT_SCHEME)에서 반환한 것과 동일합니다.

클립보드 프레임워크가 그림 1에 요약되어 있습니다. 데이터를 복사하기 위해 애플리케이션은 ClipData 객체를 ClipboardManager 전역 클립보드에 배치합니다. ClipData에는 ClipData.Item 객체 하나 이상과 ClipDescription 객체 하나가 포함됩니다. 데이터를 붙여넣기 위해 애플리케이션은 ClipData를 가져오고 ClipDescription에서 MIME 유형을 가져오며 ClipData.Item 또는 ClipData.Item에서 참조하는 콘텐츠 제공업체에서 데이터를 가져옵니다.

안드로이드 복사 붙여넣기 오류 - andeuloideu bogsa but-yeoneohgi olyu

그림 1. Android 클립보드 프레임워크

클립보드에 복사

앞서 설명한 것처럼 클립보드에 데이터를 복사하려면 전역 ClipboardManager 객체의 핸들을 가져와서 ClipData 객체를 만들고 ClipDescription 및 하나 이상의 ClipData.Item 객체를 추가한 다음 ClipboardManager 객체에 완성된 ClipData 객체를 추가하세요. 이 내용은 다음 절차에 자세히 설명되어 있습니다.

  1. 콘텐츠 URI를 사용하여 데이터를 복사하려면 콘텐츠 제공자를 설정하세요.

    노트 패드 샘플 애플리케이션은 복사하여 붙여넣기에 콘텐츠 제공자를 사용하는 예입니다. NotePadProvider 클래스는 콘텐츠 제공업체를 구현합니다. NotePad 클래스는 지원되는 MIME 유형을 포함하여 제공업체와 기타 애플리케이션 사이의 계약을 정의합니다.

  2. 시스템 클립보드 가져오기

    Kotlin

    when(menuItem.itemId) {
        ...
        R.id.menu_copy -> { // if the user selects copy
            // Gets a handle to the clipboard service.
            val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
        }
    }
    

    자바

    ...
    
    // if the user selects copy
    case R.id.menu_copy:
    
    // Gets a handle to the clipboard service.
    ClipboardManager clipboard = (ClipboardManager)
            getSystemService(Context.CLIPBOARD_SERVICE);
    

  3. 새로운 ClipData 객체로 데이터 복사하기

    • 텍스트의 경우

      Kotlin

      // Creates a new text clip to put on the clipboard
      val clip: ClipData = ClipData.newPlainText("simple text", "Hello, World!")
      

      자바

      // Creates a new text clip to put on the clipboard
      ClipData clip = ClipData.newPlainText("simple text", "Hello, World!");
      

    • URI의 경우

      이 스니펫은 제공자의 콘텐츠 URI에 레코드 ID를 인코딩하여 URI를 구성합니다. 이 기법은 URI에 식별자 인코딩 섹션에서 더 자세히 다뤄집니다.

      Kotlin

      // Creates a Uri based on a base Uri and a record ID based on the contact's last name
      // Declares the base URI string
      const val CONTACTS = "content://com.example.contacts"
      
      // Declares a path string for URIs that you use to copy data
      const val COPY_PATH = "/copy"
      
      // Declares the Uri to paste to the clipboard
      val copyUri: Uri = Uri.parse("$CONTACTS$COPY_PATH/$lastName")
      
      ...
      
      // Creates a new URI clip object. The system uses the anonymous getContentResolver() object to
      // get MIME types from provider. The clip object's label is "URI", and its data is
      // the Uri previously created.
      val clip: ClipData = ClipData.newUri(contentResolver, "URI", copyUri)
      

      자바

      // Creates a Uri based on a base Uri and a record ID based on the contact's last name
      // Declares the base URI string
      private static final String CONTACTS = "content://com.example.contacts";
      
      // Declares a path string for URIs that you use to copy data
      private static final String COPY_PATH = "/copy";
      
      // Declares the Uri to paste to the clipboard
      Uri copyUri = Uri.parse(CONTACTS + COPY_PATH + "/" + lastName);
      
      ...
      
      // Creates a new URI clip object. The system uses the anonymous getContentResolver() object to
      // get MIME types from provider. The clip object's label is "URI", and its data is
      // the Uri previously created.
      ClipData clip = ClipData.newUri(getContentResolver(), "URI", copyUri);
      

    • 인텐트의 경우

      이 스니펫은 애플리케이션의 인텐트를 구성한 다음 클립 객체에 넣습니다.

      Kotlin

      // Creates the Intent
      val appIntent = Intent(this, com.example.demo.myapplication::class.java)
      
      ...
      
      // Creates a clip object with the Intent in it. Its label is "Intent" and its data is
      // the Intent object created previously
      val clip: ClipData = ClipData.newIntent("Intent", appIntent)
      

      자바

      // Creates the Intent
      Intent appIntent = new Intent(this, com.example.demo.myapplication.class);
      
      ...
      
      // Creates a clip object with the Intent in it. Its label is "Intent" and its data is
      // the Intent object created previously
      ClipData clip = ClipData.newIntent("Intent", appIntent);
      

  4. 새로운 클립 객체를 클립보드에 배치합니다.

    Kotlin

    // Set the clipboard's primary clip.
    clipboard.setPrimaryClip(clip)
    

    자바

    // Set the clipboard's primary clip.
    clipboard.setPrimaryClip(clip);
    

클립보드에서 붙여넣기

앞서 설명한 것처럼 전역 클립보드 객체와 클립 객체를 가져와서 데이터를 살펴본 다음 가능하다면 클립 객체의 데이터를 자체 저장소에 복사하여 클립보드에서 데이터를 붙여넣습니다. 이 섹션에서는 세 가지 클립보드 데이터 형식에 이 작업을 실행하는 방법을 자세히 설명합니다.

일반 텍스트 붙여넣기

일반 텍스트를 붙여넣으려면 먼저 전역 클립보드를 가져와서 일반 텍스트를 반환할 수 있는지 확인합니다. 그리고 다음 절차에서 설명하는 것처럼 클립 객체를 가져와서 getText()를 사용하여 텍스트를 자체 저장소에 복사합니다.

  1. getSystemService(CLIPBOARD_SERVICE)를 사용하여 전역 ClipboardManager 객체를 가져옵니다. 전역 변수를 선언하여 붙여넣은 텍스트도 포함합니다.

    Kotlin

    var clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    var pasteData: String = ""
    

    자바

    ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    String pasteData = "";
    

  2. 다음으로 현재 활동에서 '붙여넣기' 옵션을 사용 설정 또는 사용 중지해야 하는지 확인합니다. 클립보드에 클립이 포함되어 있는지 클립이 표시하는 데이터 유형을 처리할 수 있는지 확인해야 합니다.

    Kotlin

    // Gets the ID of the "paste" menu item
    val pasteItem: MenuItem = menu.findItem(R.id.menu_paste)
    
    // If the clipboard doesn't contain data, disable the paste menu item.
    // If it does contain data, decide if you can handle the data.
    pasteItem.isEnabled = when {
        !clipboard.hasPrimaryClip() -> {
            false
        }
        !(clipboard.primaryClipDescription.hasMimeType(MIMETYPE_TEXT_PLAIN)) -> {
            // This disables the paste menu item, since the clipboard has data but it is not plain text
            false
        }
        else -> {
            // This enables the paste menu item, since the clipboard contains plain text.
            true
        }
    }
    

    자바

    // Gets the ID of the "paste" menu item
    MenuItem pasteItem = menu.findItem(R.id.menu_paste);
    
    // If the clipboard doesn't contain data, disable the paste menu item.
    // If it does contain data, decide if you can handle the data.
    if (!(clipboard.hasPrimaryClip())) {
    
        pasteItem.setEnabled(false);
    
    } else if (!(clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN))) {
    
        // This disables the paste menu item, since the clipboard has data but it is not plain text
        pasteItem.setEnabled(false);
    } else {
    
        // This enables the paste menu item, since the clipboard contains plain text.
        pasteItem.setEnabled(true);
    }
    

  3. 클립보드에서 데이터를 복사합니다. 프로그램의 이 지점은 '붙여넣기' 메뉴 항목이 사용 설정된 경우에만 도달할 수 있으므로 클립보드에 일반 텍스트가 포함되어 있다고 가정할 수 있습니다. 텍스트 문자열이나 일반 텍스트를 가리키는 URI가 포함되어 있는지는 아직 모릅니다. 다음 스니펫은 이를 테스트하지만 일반 텍스트를 처리하는 코드만 표시합니다.

    Kotlin

    when (menuItem.itemId) {
        ...
        R.id.menu_paste -> {    // Responds to the user selecting "paste"
            // Examines the item on the clipboard. If getText() does not return null, the clip item
            // contains the text. Assumes that this application can only handle one item at a time.
            val item = clipboard.primaryClip.getItemAt(0)
    
            // Gets the clipboard as text.
            pasteData = item.text
    
            return if (pasteData != null) {
                // If the string contains data, then the paste operation is done
                true
            } else {
                // The clipboard does not contain text.
                // If it contains a URI, attempts to get data from it
                val pasteUri: Uri? = item.uri
    
                if (pasteUri != null) {
                    // If the URI contains something, try to get text from it
    
                    // calls a routine to resolve the URI and get data from it. This routine is not
                    // presented here.
                    pasteData = resolveUri(pasteUri)
                    true
                } else {
    
                    // Something is wrong. The MIME type was plain text, but the clipboard does not
                    // contain either text or a Uri. Report an error.
                    Log.e(TAG,"Clipboard contains an invalid data type")
                    false
                }
            }
        }
    }
    

    자바

    // Responds to the user selecting "paste"
    case R.id.menu_paste:
    
    // Examines the item on the clipboard. If getText() does not return null, the clip item contains the
    // text. Assumes that this application can only handle one item at a time.
     ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
    
    // Gets the clipboard as text.
    pasteData = item.getText();
    
    // If the string contains data, then the paste operation is done
    if (pasteData != null) {
        return true;
    
    // The clipboard does not contain text. If it contains a URI, attempts to get data from it
    } else {
        Uri pasteUri = item.getUri();
    
        // If the URI contains something, try to get text from it
        if (pasteUri != null) {
    
            // calls a routine to resolve the URI and get data from it. This routine is not
            // presented here.
            pasteData = resolveUri(Uri);
            return true;
        } else {
    
            // Something is wrong. The MIME type was plain text, but the clipboard does not contain either
            // text or a Uri. Report an error.
            Log.e(TAG, "Clipboard contains an invalid data type");
            return false;
        }
    }
    

콘텐츠 URI에서 데이터 붙여넣기

ClipData.Item 객체에 콘텐츠 URI가 포함되어 있고 MIME 유형 중 하나를 처리할 수 있다고 판단되면 ContentResolver를 만들고 적절한 콘텐츠 제공업체 메서드를 호출하여 데이터를 검색합니다.

다음 절차에서는 클립보드의 콘텐츠 URI에 기반한 콘텐츠 제공업체에서 데이터를 가져오는 방법을 설명합니다. 애플리케이션이 사용할 수 있는 MIME 유형이 제공업체에서 제공되는지 확인합니다.

  1. 전역 변수를 선언하여 MIME 유형을 포함합니다.

    Kotlin

    // Declares a MIME type constant to match against the MIME types offered by the provider
    const val MIME_TYPE_CONTACT = "vnd.android.cursor.item/vnd.example.contact"
    

    자바

    // Declares a MIME type constant to match against the MIME types offered by the provider
    public static final String MIME_TYPE_CONTACT = "vnd.android.cursor.item/vnd.example.contact";
    

  2. 전역 클립보드 가져오기 또한 콘텐츠 리졸버를 가져와서 콘텐츠 제공업체에 액세스할 수 있습니다.

    Kotlin

    // Gets a handle to the Clipboard Manager
    val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    
    // Gets a content resolver instance
    val cr = contentResolver
    

    자바

    // Gets a handle to the Clipboard Manager
    ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    
    // Gets a content resolver instance
    ContentResolver cr = getContentResolver();
    

  3. 클립보드에서 기본 클립을 가져오고 그 콘텐츠를 URI로 가져옵니다.

    Kotlin

    // Gets the clipboard data from the clipboard
    val clip: ClipData? = clipboard.primaryClip
    
    clip?.run {
    
        // Gets the first item from the clipboard data
        val item: ClipData.Item = getItemAt(0)
    
        // Tries to get the item's contents as a URI
        val pasteUri: Uri? = item.uri
    

    자바

    // Gets the clipboard data from the clipboard
    ClipData clip = clipboard.getPrimaryClip();
    
    if (clip != null) {
    
        // Gets the first item from the clipboard data
        ClipData.Item item = clip.getItemAt(0);
    
        // Tries to get the item's contents as a URI
        Uri pasteUri = item.getUri();
    

  4. getType(Uri)을 호출하여 URI가 콘텐츠 URI인지 테스트합니다. 이 메서드는 Uri가 유효한 콘텐츠 제공업체를 가리키지 않으면 null을 반환합니다.

    Kotlin

        // If the clipboard contains a URI reference
        pasteUri?.let {
    
            // Is this a content URI?
            val uriMimeType: String? = cr.getType(it)
    

    자바

        // If the clipboard contains a URI reference
        if (pasteUri != null) {
    
            // Is this a content URI?
            String uriMimeType = cr.getType(pasteUri);
    

  5. 콘텐츠 제공업체가 현재 애플리케이션이 이해하는 MIME 유형을 지원하는지 테스트합니다. 지원한다면 ContentResolver.query()를 호출하여 데이터를 가져옵니다. 반환값은 Cursor입니다.

    Kotlin

            // If the return value is not null, the Uri is a content Uri
            uriMimeType?.takeIf {
    
                // Does the content provider offer a MIME type that the current application can use?
                it == MIME_TYPE_CONTACT
            }?.apply {
    
                // Get the data from the content provider.
                cr.query(pasteUri, null, null, null, null)?.use { pasteCursor ->
    
                    // If the Cursor contains data, move to the first record
                    if (pasteCursor.moveToFirst()) {
    
                        // get the data from the Cursor here. The code will vary according to the
                        // format of the data model.
                    }
    
                    // Kotlin `use` will automatically close the Cursor
                }
            }
        }
    }
    

    자바

            // If the return value is not null, the Uri is a content Uri
            if (uriMimeType != null) {
    
                // Does the content provider offer a MIME type that the current application can use?
                if (uriMimeType.equals(MIME_TYPE_CONTACT)) {
    
                    // Get the data from the content provider.
                    Cursor pasteCursor = cr.query(uri, null, null, null, null);
    
                    // If the Cursor contains data, move to the first record
                    if (pasteCursor != null) {
                        if (pasteCursor.moveToFirst()) {
    
                        // get the data from the Cursor here. The code will vary according to the
                        // format of the data model.
                        }
                    }
    
                    // close the Cursor
                    pasteCursor.close();
                 }
             }
         }
    }
    

인텐트 붙여넣기

인텐트를 붙여넣으려면 먼저 전역 클립보드를 가져옵니다. ClipData.Item 객체를 검사하여 인텐트가 포함되어 있는지 확인합니다. 그런 다음 getIntent()를 호출하여 인텐트를 자체 저장소에 복사합니다. 다음 스니펫은 이 작업을 보여줍니다.

Kotlin

// Gets a handle to the Clipboard Manager
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager

// Checks to see if the clip item contains an Intent, by testing to see if getIntent() returns null
val pasteIntent: Intent? = clipboard.primaryClip?.getItemAt(0)?.intent

if (pasteIntent != null) {

    // handle the Intent

} else {

    // ignore the clipboard, or issue an error if your application was expecting an Intent to be
    // on the clipboard
}

자바

// Gets a handle to the Clipboard Manager
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);

// Checks to see if the clip item contains an Intent, by testing to see if getIntent() returns null
Intent pasteIntent = clipboard.getPrimaryClip().getItemAt(0).getIntent();

if (pasteIntent != null) {

    // handle the Intent

} else {

    // ignore the clipboard, or issue an error if your application was expecting an Intent to be
    // on the clipboard
}

콘텐츠 제공업체를 사용하여 복잡한 데이터 복사

콘텐츠 제공업체는 데이터베이스 레코드나 파일 스트림과 같은 복잡한 데이터의 복사를 지원합니다. 데이터를 복사하려면 콘텐츠 URI를 클립보드에 배치합니다. 그러면 붙여넣기 애플리케이션이 클립보드에서 URI를 가져와서 데이터베이스 데이터나 파일 스트림 설명어를 검색하는 데 사용합니다.

붙여넣기 애플리케이션에는 데이터의 콘텐츠 URI만 있으므로 어떤 데이터 조각을 검색할지 알아야 합니다. URI 자체에 데이터 식별자를 인코딩하여 이 정보를 제공하거나 복사하려는 데이터를 반환하는 고유한 URI를 제공할 수 있습니다. 데이터 구성에 따라 선택하는 기법이 달라집니다.

다음 섹션에서는 URI를 설정하는 방법과 복잡한 데이터 및 파일 스트림을 제공하는 방법을 설명합니다. 설명에서는 개발자가 콘텐츠 제공업체 디자인의 일반 원칙을 잘 알고 있다고 가정합니다.

URI에 식별자 인코딩

URI를 사용하여 클립보드에 데이터를 복사하는 유용한 기법은 URI 자체에 데이터 식별자를 인코딩하는 것입니다. 그러면 콘텐츠 제공업체가 URI에서 식별자를 가져와서 데이터 검색에 사용할 수 있습니다. 붙여넣기 애플리케이션은 식별자가 있는지 알 필요가 없습니다. 해야 할 작업은 클립보드에서 '참조'(URI와 식별자)를 가져와서 콘텐츠 제공업체에 제공하고 데이터를 다시 가져오는 것뿐입니다.

일반적으로 식별자를 URI 끝에 연결하여 콘텐츠 URI에 식별자를 인코딩합니다. 예를 들어 제공업체 URI를 다음 문자열로 정의한다고 가정해보겠습니다.

"content://com.example.contacts"

이 URI에 이름을 인코딩하려면 다음 스니펫을 사용할 수 있습니다.

Kotlin

val uriString = "content://com.example.contacts/Smith"

// uriString now contains content://com.example.contacts/Smith.

// Generates a uri object from the string representation
val copyUri = Uri.parse(uriString)

자바

String uriString = "content://com.example.contacts" + "/" + "Smith";

// uriString now contains content://com.example.contacts/Smith.

// Generates a uri object from the string representation
Uri copyUri = Uri.parse(uriString);

콘텐츠 제공업체를 이미 사용하고 있다면 URI가 복사용인 것을 표시하는 새로운 URI 경로를 추가하는 것이 좋습니다. 예를 들어 다음 URI 경로가 이미 있다고 가정해보겠습니다.

"content://com.example.contacts"/people
"content://com.example.contacts"/people/detail
"content://com.example.contacts"/people/images

URI 복사에 특수한 또 다른 경로를 추가할 수 있습니다.

"content://com.example.contacts/copying"

그런 다음 패턴 일치를 통해 '복사' URI를 감지하고 복사하여 붙여넣기용 특수 코드를 사용하여 처리할 수 있습니다.

이미 콘텐츠 제공업체나 내부 데이터베이스, 내부 테이블을 사용하여 데이터를 체계화하는 경우 일반적으로 인코딩 기법을 사용합니다. 이러한 경우 복사하려는 여러 데이터 조각이 있고 각 조각에 고유한 식별자가 있을 수 있습니다. 붙여넣기 애플리케이션의 쿼리에 대한 응답으로 데이터를 식별자로 찾아서 반환할 수 있습니다.

여러 데이터 조각이 없으면 식별자를 인코딩하지 않아도 됩니다. 제공업체에 고유한 URI를 간단히 사용할 수 있습니다. 쿼리에 대한 응답으로 제공업체는 현재 포함된 데이터를 반환할 수 있습니다.

ID로 단일 레코드 가져오기는 노트 패드 샘플 애플리케이션이 메모 목록에서 메모를 여는 데 사용합니다. 이 샘플에서는 SQL 데이터베이스의 _id 필드를 사용하지만 원하는 숫자 또는 문자 식별자를 모두 가질 수 있습니다.

데이터 구조 복사

복잡한 데이터를 복사하여 붙여넣기 위해 콘텐츠 제공업체를 ContentProvider 구성요소의 서브클래스로 설정합니다. 클립보드에 배치한 URI도 인코딩하여 제공하려는 정확한 레코드를 가리키도록 해야 합니다. 또한 애플리케이션의 기존 상태를 고려해야 합니다.

  • 콘텐츠 제공업체가 이미 있는 경우 기능에 추가할 수 있습니다. 데이터를 붙여넣으려는 애플리케이션에서 나오는 URI를 처리하기 위해 query() 메서드만 수정해야 할 수 있습니다. 메서드를 수정하여 '복사' URI 패턴을 처리하는 것이 좋습니다.
  • 애플리케이션에서 내부 데이터베이스를 유지 관리하는 경우 이 데이터베이스를 콘텐츠 제공업체로 이동하여 복사를 용이하게 하는 것이 좋습니다.
  • 현재 데이터베이스를 사용하지 않는 경우 클립보드에서 붙여넣기 하는 애플리케이션에 데이터를 제공하는 것이 유일한 목적인 단순한 콘텐츠 제공업체를 구현할 수 있습니다.

콘텐츠 제공업체에서 적어도 다음 메서드를 재정의하는 것이 좋습니다.

query()붙여넣기 애플리케이션은 클립보드에 배치한 URI와 함께 이 메서드를 사용하여 데이터를 가져올 수 있다고 가정합니다. 복사를 지원하려면 이 메서드에서 특수한 '복사' 경로가 포함된 URI를 감지해야 합니다. 그런 다음 애플리케이션에서 '복사' URI를 만들어 복사 경로와 복사하려는 정확한 레코드의 포인터를 포함하는 클립보드에 배치할 수 있습니다. getType()이 메서드는 복사하려는 데이터의 MIME 유형을 반환해야 합니다. MIME 유형을 새로운 ClipData 객체에 넣기 위해 메서드 newUri()getType()을 호출합니다.

복잡한 데이터의 MIME 유형은 콘텐츠 제공자 주제에 설명되어 있습니다.

insert() 또는 update()와 같은 다른 콘텐츠 제공업체 메서드를 보유할 필요는 없습니다. 붙여넣기 애플리케이션은 지원되는 MIME 유형만 가져와서 제공업체의 데이터를 복사하면 됩니다. 이러한 메서드가 이미 있다면 복사 작업을 방해하지 않습니다.

다음 스니펫은 애플리케이션을 설정하여 복잡한 데이터를 복사하는 방법을 보여줍니다.

  1. 애플리케이션의 전역 상수에서 데이터를 복사하는 데 사용하는 URI 문자열을 식별하는 경로와 기본 URI 문자열을 선언합니다. 복사된 데이터의 MIME 유형도 선언합니다.

    Kotlin

    // Declares the base URI string
    private const val CONTACTS = "content://com.example.contacts"
    
    // Declares a path string for URIs that you use to copy data
    private const val COPY_PATH = "/copy"
    
    // Declares a MIME type for the copied data
    const val MIME_TYPE_CONTACT = "vnd.android.cursor.item/vnd.example.contact"
    

    자바

    // Declares the base URI string
    private static final String CONTACTS = "content://com.example.contacts";
    
    // Declares a path string for URIs that you use to copy data
    private static final String COPY_PATH = "/copy";
    
    // Declares a MIME type for the copied data
    public static final String MIME_TYPE_CONTACT = "vnd.android.cursor.item/vnd.example.contact";
    

  2. 사용자가 데이터를 복사하는 활동에서 코드를 설정하여 데이터를 클립보드에 복사합니다. 복사 요청에 대한 응답으로 클립보드에 URI를 배치합니다.

    Kotlin

    class MyCopyActivity : Activity() {
    
        ...
    
    when(item.itemId) {
        R.id.menu_copy -> { // The user has selected a name and is requesting a copy.
            // Appends the last name to the base URI
            // The name is stored in "lastName"
            uriString = "$CONTACTS$COPY_PATH/$lastName"
    
            // Parses the string into a URI
            val copyUri: Uri? = Uri.parse(uriString)
    
            // Gets a handle to the clipboard service.
            val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    
            val clip: ClipData = ClipData.newUri(contentResolver, "URI", copyUri)
    
            // Set the clipboard's primary clip.
            clipboard.setPrimaryClip(clip)
        }
    }
    

    자바

    public class MyCopyActivity extends Activity {
    
        ...
    
    // The user has selected a name and is requesting a copy.
    case R.id.menu_copy:
    
        // Appends the last name to the base URI
        // The name is stored in "lastName"
        uriString = CONTACTS + COPY_PATH + "/" + lastName;
    
        // Parses the string into a URI
        Uri copyUri = Uri.parse(uriString);
    
        // Gets a handle to the clipboard service.
        ClipboardManager clipboard = (ClipboardManager)
            getSystemService(Context.CLIPBOARD_SERVICE);
    
        ClipData clip = ClipData.newUri(getContentResolver(), "URI", copyUri);
    
        // Set the clipboard's primary clip.
        clipboard.setPrimaryClip(clip);
    

  3. 콘텐츠 제공업체의 전역 범위에서 URI 매처를 만들고 클립보드에 배치한 URI와 일치할 URI 패턴을 추가하세요.

    Kotlin

    // A Uri Match object that simplifies matching content URIs to patterns.
    private val sUriMatcher = UriMatcher(UriMatcher.NO_MATCH).apply {
    
        // Adds a matcher for the content URI. It matches
        // "content://com.example.contacts/copy/*"
        addURI(CONTACTS, "names/*", GET_SINGLE_CONTACT)
    }
    
    // An integer to use in switching based on the incoming URI pattern
    private const val GET_SINGLE_CONTACT = 0
    
    ...
    
    class MyCopyProvider : ContentProvider() {
        ...
    }
    

    자바

    public class MyCopyProvider extends ContentProvider {
    
        ...
    
    // A Uri Match object that simplifies matching content URIs to patterns.
    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    
    // An integer to use in switching based on the incoming URI pattern
    private static final int GET_SINGLE_CONTACT = 0;
    
    ...
    
    // Adds a matcher for the content URI. It matches
    // "content://com.example.contacts/copy/*"
    sUriMatcher.addURI(CONTACTS, "names/*", GET_SINGLE_CONTACT);
    

  4. query() 메서드를 설정합니다. 이 메서드는 코딩 방법에 따라 다양한 URI 패턴을 처리할 수 있지만 클립보드 복사 작업의 패턴만 표시됩니다.

    Kotlin

    // Sets up your provider's query() method.
    override fun query(
            uri: Uri,
            projection: Array<out String>?,
            selection: String?,
            selectionArgs: Array<out String>?,
            sortOrder: String?
    ): Cursor? {
    
        ...
    
        // when based on the incoming content URI
        when(sUriMatcher.match(uri)) {
    
            GET_SINGLE_CONTACT -> {
    
                // query and return the contact for the requested name. Here you would decode
                // the incoming URI, query the data model based on the last name, and return the result
                // as a Cursor.
            }
        }
    
        ...
    
    }
    

    자바

    // Sets up your provider's query() method.
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
        String sortOrder) {
    
        ...
    
        // Switch based on the incoming content URI
        switch (sUriMatcher.match(uri)) {
    
        case GET_SINGLE_CONTACT:
    
            // query and return the contact for the requested name. Here you would decode
            // the incoming URI, query the data model based on the last name, and return the result
            // as a Cursor.
    
        ...
    
    }
    

  5. getType() 메서드를 설정하여 복사된 데이터에 적절한 MIME 유형을 반환하세요.

    Kotlin

    // Sets up your provider's getType() method.
    override fun getType(uri: Uri): String? {
        ...
    
        return when(sUriMatcher.match(uri)) {
            GET_SINGLE_CONTACT -> MIME_TYPE_CONTACT
            ...
        }
    }
    

    자바

    // Sets up your provider's getType() method.
    public String getType(Uri uri) {
        ...
    
        switch (sUriMatcher.match(uri)) {
        case GET_SINGLE_CONTACT:
            return (MIME_TYPE_CONTACT);
        ...
        }
    }
    

콘텐츠 URI에서 데이터 붙여넣기 섹션에서는 클립보드에서 콘텐츠 URI를 가져와서 데이터를 가져오고 붙여넣는 데 사용하는 방법을 설명합니다.

데이터 스트림 복사

대량의 텍스트 및 바이너리 데이터를 스트림으로 복사하여 붙여넣기 할 수 있습니다. 데이터는 다음과 같은 형식일 수 있습니다.

  • 실제 기기에 저장된 파일
  • 소켓 스트림
  • 제공업체의 기본 데이터베이스 시스템에 저장된 대량의 데이터

데이터 스트림용 콘텐츠 제공업체는 Cursor 객체가 아닌 AssetFileDescriptor와 같은 파일 설명자 객체를 사용하여 데이터에 액세스할 수 있도록 합니다. 붙여넣기 애플리케이션은 파일 설명자를 사용하여 데이터 스트림을 읽습니다.

애플리케이션을 설정하여 제공업체와 함께 데이터 스트림을 복사하려면 다음 단계를 따르세요.

  1. 클립보드에 배치하는 데이터 스트림의 콘텐츠 URI를 설정합니다. 이 작업 실행의 옵션에는 다음이 포함됩니다.
    • URI에 식별자 인코딩 섹션에서 설명한 것처럼 URI에 데이터 스트림의 식별자를 인코딩하고 식별자와 그에 상응하는 스트림 이름이 포함된 테이블을 제공업체에 유지합니다.
    • 스트림 이름을 URI에 직접 인코딩합니다.
    • 항상 제공업체의 현재 스트림을 반환하는 고유한 URI를 사용합니다. 이 옵션을 사용하는 경우 URI를 통해 클립보드에 스트림을 복사할 때마다 제공업체를 업데이트하여 다른 스트림을 가리키도록 해야 합니다.
  2. 제공하려는 각 데이터 스트림 유형에 MIME 유형을 제공합니다. 붙여넣기 애플리케이션에는 데이터를 클립보드에 붙여넣을 수 있는지 확인하기 위해 이 정보가 필요합니다.
  3. 스트림의 파일 설명자를 반환하는 ContentProvider 메서드 중 하나를 구현합니다. 콘텐츠 URI에 식별자를 인코딩한다면 이 메서드를 사용하여 어떤 스트림을 열 것인지 확인합니다.
  4. 데이터 스트림을 클립보드에 복사하려면 콘텐츠 URI를 구성하여 클립보드에 배치합니다.

데이터 스트림을 붙여넣으려면 애플리케이션은 클립보드에서 클립을 가져오고 URI를 가져와서 스트림을 여는 ContentResolver 파일 설명자 메서드를 호출하는 데 사용합니다. ContentResolver 메서드는 상응하는 ContentProvider 메서드를 호출하여 콘텐츠 URI를 전달합니다. 제공업체는 파일 설명자를 ContentResolver 메서드에 반환합니다. 그러면 붙여넣기 애플리케이션은 스트림에서 데이터를 읽어야 합니다.

다음 목록은 콘텐츠 제공업체의 가장 중요한 파일 설명자 메서드를 보여줍니다. 각각에는 메서드 이름에 추가된 문자열 '설명어'와 함께 상응하는 ContentResolver 메서드가 있습니다. 예를 들어 openAssetFile()ContentResolver 아날로그는 openAssetFileDescriptor()입니다.

openTypedAssetFile()이 메서드는 제공된 MIME 유형을 제공업체에서 지원하는 경우에만 애셋 파일 설명자를 반환해야 합니다. 호출자(붙여넣기를 실행하는 애플리케이션)는 MIME 유형 패턴을 제공합니다. URI를 클립보드에 복사한 애플리케이션의 콘텐츠 제공업체는 MIME 유형을 제공할 수 있는 경우 AssetFileDescriptor 파일 핸들을 반환하고 제공할 수 없는 경우 예외를 발생시킵니다.

이 메서드는 파일의 하위 섹션을 처리합니다. 이 메서드를 사용하여 콘텐츠 제공업체가 클립보드에 복사한 애셋을 읽을 수 있습니다.

openAssetFile()이 메서드는 더 일반적인 형식의 openTypedAssetFile()입니다. 허용된 MIME 유형은 필터링하지 않지만 파일의 하위 섹션은 읽을 수 있습니다. openFile()더 일반적인 형식의 openAssetFile()입니다. 파일의 하위 섹션을 읽을 수 없습니다.

파일 설명자 메서드와 함께 선택적으로 openPipeHelper() 메서드를 사용할 수 있습니다. 이렇게 하면 붙여넣기 애플리케이션이 파이프를 사용하여 백그라운드 스레드에서 스트림 데이터를 읽을 수 있습니다. 이 메서드를 사용하려면 ContentProvider.PipeDataWriter 인터페이스를 구현해야 합니다. 이 작업의 실행 예는 노트 패드 샘플 애플리케이션에서 NotePadProvider.javaopenTypedAssetFile() 메서드로 제공됩니다.

효과적인 복사/붙여넣기 기능 디자인

애플리케이션에 효과적인 복사하여 붙여넣기 기능을 디자인하려면 다음 사항에 유의하세요.

  • 언제나 클립보드에는 클립이 하나만 있습니다. 시스템의 모든 애플리케이션에서 실행하는 새로운 복사 작업은 이전 클립을 덮어씁니다. 사용자가 애플리케이션에서 이동하여 돌아오기 전에 복사할 수 있으므로 클립보드에 사용자가 개발자의 애플리케이션에서 이전에 복사한 클립이 포함되어 있다고 가정할 수 없습니다.
  • 클립당 여러 ClipData.Item 객체의 용도는 다양한 형식의 단일 선택 참조가 아니라 여러 선택의 복사하여 붙여넣기를 지원하는 것입니다. 개발자는 일반적으로 클립의 ClipData.Item 객체가 모두 동일한 형식이기를 바랍니다. 즉, 모두 단순하게 텍스트나 콘텐츠 URI, Intent여야 하고 혼합되어서는 안 됩니다.
  • 데이터를 제공할 때 다양한 MIME 표시를 제공할 수 있습니다. 지원하는 MIME 유형을 ClipDescription에 추가하고 콘텐츠 제공업체에서 MIME 유형을 구현하세요.
  • 클립보드에서 데이터를 가져올 때 애플리케이션은 사용 가능한 MIME 유형을 확인하고 사용할 MIME 유형을 판단해야 합니다. 클립보드에 클립이 있고 사용자가 붙여넣기를 요청하더라도 애플리케이션은 붙여넣기를 실행할 필요가 없습니다. MIME 유형이 호환되는 경우 개발자는 붙여넣기를 실행해야 합니다. 원한다면 coerceToText()를 사용하여 클립보드의 데이터를 텍스트로 강제 변환할 수도 있습니다. 애플리케이션이 사용 가능한 MIME 유형을 둘 이상 지원하는 경우 사용자가 사용할 유형을 선택할 수 있습니다.