Google은 흑인 공동체를 위한 인종 간 평등을 진전시키기 위해 노력하고 있습니다. Google에서 어떤 노력을 하고 있는지 확인하세요.

NFC로 다른 기기에 파일 전송

이 과정에서는 Android Beam 파일 전송을 사용하여 다른 기기로 대용량 파일을 전송하도록 앱을 설계하는 방법에 관해 설명합니다. 파일을 전송하려면 NFC와 외부 저장소의 사용 권한을 요청하고 기기에서 NFC를 지원하는지 테스트한 후 Android Beam 파일 전송에 URI를 제공합니다.

Android Beam 파일 전송 기능의 요구사항은 다음과 같습니다.

  1. 대용량 파일을 위한 Android Beam 파일 전송은 Android 4.1(API 수준 16) 이상에서만 사용할 수 있습니다.
  2. 전송하려는 파일은 외부 저장소에 있어야 합니다. 외부 저장소 사용 방법에 관해 자세히 알아보려면 외부 저장소 사용을 참조하세요.
  3. 전송하려는 각 파일은 누구나 읽을 수 있어야 합니다. File.setReadable(true,false) 메서드를 호출하여 이 권한을 설정할 수 있습니다.
  4. 전송하려는 파일의 파일 URI를 제공해야 합니다. Android Beam 파일 전송은 FileProvider.getUriForFile에서 생성된 콘텐츠 URI를 처리할 수 없습니다.

매니페스트에 기능 선언

먼저 앱의 manifest를 수정하여 앱에 필요한 권한과 기능을 선언합니다.

권한 요청

앱이 Android Beam 파일 전송을 사용하여 NFC를 통해 외부 저장소에서 파일을 전송할 수 있으려면 앱 매니페스트에서 다음 권한을 요청해야 합니다.

NFC
앱이 NFC를 통해 데이터를 전송하도록 허용합니다. 이 권한을 지정하려면 다음 요소를 <manifest> 요소의 하위 요소로 추가하세요.
        <uses-permission android:name="android.permission.NFC" />
    
READ_EXTERNAL_STORAGE
앱이 외부 저장소에서 정보를 읽을 수 있도록 허용합니다. 이 권한을 지정하려면 다음 요소를 <manifest> 요소의 하위 요소로 추가하세요.
        <uses-permission
                android:name="android.permission.READ_EXTERNAL_STORAGE" />
    

참고: Android 4.2.2(API 수준 17)부터 이 권한은 사용되지 않습니다. 플랫폼의 향후 버전에서는 외부 저장소에서 데이터를 읽어오려는 앱에 이 권한을 요구할 수 있습니다. 이후 버전과 호환성을 유지하려면 플랫폼에서 요구하기 전에 지금 권한을 요청하세요.

NFC 기능 지정

<uses-feature> 요소를 <manifest> 요소의 하위 요소로 추가하여 앱에서 NFC를 사용하도록 지정합니다. android:required 속성을 true로 설정하여 NFC가 없으면 앱이 작동하지 않는다고 나타냅니다.

다음 스니펫은 <uses-feature> 요소를 지정하는 방법을 보여줍니다.

    <uses-feature
        android:name="android.hardware.nfc"
        android:required="true" />

앱에서 옵션으로만 NFC를 사용하고 NFC가 없는데도 여전히 작동한다면 android:requiredfalse로 설정하고 코드에서 NFC를 테스트해야 합니다.

Android Beam 파일 전송 지정

Android Beam 파일 전송은 Android 4.1(API 수준 16) 이상에서만 사용할 수 있으므로 앱의 주요 기능에서 Android Beam 파일 전송을 사용한다면 android:minSdkVersion="16" 속성으로 <uses-sdk>를 지정해야 합니다. 지정하지 않으면 필요에 따라 다른 값으로 android:minSdkVersion을 설정하고 다음 섹션에서 설명하는 대로 코드에서 플랫폼 버전을 테스트할 수 있습니다.

Android Beam 파일 전송 지원 테스트

앱 매니페스트에서 NFC가 선택사항이라고 지정하려면 다음 요소를 사용하세요.

    <uses-feature android:name="android.hardware.nfc" android:required="false" />

android:required="false" 속성을 설정하면 코드에서 NFC 지원과 Android Beam 파일 전송 지원을 테스트해야 합니다.

코드에서 Android Beam 파일 전송 지원을 테스트하려면 먼저 FEATURE_NFC 인수로 PackageManager.hasSystemFeature()를 호출하여 기기에서 NFC를 지원하는지 테스트합니다. 그런 다음 SDK_INT 값을 테스트하여 Android 버전에서 Android Beam 파일 전송을 지원하는지 확인합니다. Android Beam 파일 전송이 지원된다면 NFC 하드웨어와 통신할 수 있는 NFC 컨트롤러 인스턴스를 가져옵니다. 예:

Kotlin

    class MainActivity : Activity() {
        ...
        private lateinit var nfcAdapter: NfcAdapter
        // Flag to indicate that Android Beam is available
        private var androidBeamAvailable = false
        ...
        override fun onCreate(savedInstanceState: Bundle?) {
            ...
            androidBeamAvailable = if (!packageManager.hasSystemFeature(PackageManager.FEATURE_NFC)) {
                // NFC isn't available on the device
                /*
                  * Disable NFC features here.
                  * For example, disable menu items or buttons that activate
                  * NFC-related features
                  */
                false
            // Android Beam file transfer isn't supported
            } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
                // If Android Beam isn't available, don't continue.
                androidBeamAvailable = false
                /*
                 * Disable Android Beam file transfer features here.
                 */
                ...
                false
            } else {
                // Android Beam file transfer is available, continue
                nfcAdapter = NfcAdapter.getDefaultAdapter(this)
                ...
                true
            }
        }
        ...
    }
    

자바

    public class MainActivity extends Activity {
        ...
        NfcAdapter nfcAdapter;
        // Flag to indicate that Android Beam is available
        boolean androidBeamAvailable  = false;
        ...
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            ...
            // NFC isn't available on the device
            if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) {
                /*
                 * Disable NFC features here.
                 * For example, disable menu items or buttons that activate
                 * NFC-related features
                 */
                ...
            // Android Beam file transfer isn't supported
            } else if (Build.VERSION.SDK_INT <
                    Build.VERSION_CODES.JELLY_BEAN_MR1) {
                // If Android Beam isn't available, don't continue.
                androidBeamAvailable = false;
                /*
                 * Disable Android Beam file transfer features here.
                 */
                ...
            // Android Beam file transfer is available, continue
            } else {
                androidBeamAvailable = true;
                nfcAdapter = NfcAdapter.getDefaultAdapter(this);
            ...
            }
        }
        ...
    }
    

파일을 제공하는 콜백 메서드 만들기

기기에서 Android Beam 파일 전송을 지원하는지 확인한 후에는, 사용자가 다른 NFC 지원 기기로 파일을 전송하려고 하는 것을 Android Beam 파일 전송이 감지할 때 시스템에서 호출하는 콜백 메서드를 추가합니다. 이 콜백 메서드에서 Uri 객체의 배열을 반환하세요. Android Beam 파일 전송은 이 URI에서 표시한 파일을 수신 기기에 복사합니다.

콜백 메서드를 추가하려면 NfcAdapter.CreateBeamUrisCallback 인터페이스와 인터페이스의 createBeamUris() 메서드를 구현합니다. 다음 스니펫은 구현 방법을 보여줍니다.

Kotlin

    public class MainActivity : Activity() {
        ...
        // List of URIs to provide to Android Beam
        private val fileUris = mutableListOf<Uri>()
        ...
        /**
         * Callback that Android Beam file transfer calls to get
         * files to share
         */
        private inner class FileUriCallback : NfcAdapter.CreateBeamUrisCallback {
            /**
             * Create content URIs as needed to share with another device
             */
            override fun createBeamUris(event: NfcEvent): Array<Uri> {
                return fileUris.toTypedArray()
            }
        }
        ...
    }
    

자바

    public class MainActivity extends Activity {
        ...
        // List of URIs to provide to Android Beam
        private Uri[] fileUris = new Uri[10];
        ...
        /**
         * Callback that Android Beam file transfer calls to get
         * files to share
         */
        private class FileUriCallback implements
                NfcAdapter.CreateBeamUrisCallback {
            public FileUriCallback() {
            }
            /**
             * Create content URIs as needed to share with another device
             */
            @Override
            public Uri[] createBeamUris(NfcEvent event) {
                return fileUris;
            }
        }
        ...
    }
    

인터페이스를 구현한 후에는 setBeamPushUrisCallback()을 호출하여 Android Beam 파일 전송에 콜백을 제공하세요. 다음 스니펫은 구현 방법을 보여줍니다.

Kotlin

    class MainActivity : Activity() {
        ...
        private lateinit var nfcAdapter: NfcAdapter
        // Flag to indicate that Android Beam is available
        private var androidBeamAvailable = false
        ...
        override fun onCreate(savedInstanceState: Bundle?) {
            ...
            // Android Beam file transfer is available, continue
            nfcAdapter = NfcAdapter.getDefaultAdapter(this).apply {

                /*
                 * Instantiate a new FileUriCallback to handle requests for
                 * URIs
                 */
                fileUriCallback = FileUriCallback()
                // Set the dynamic callback for URI requests.
                nfcAdapter.setBeamPushUrisCallback(fileUriCallback, this@MainActivity)
            }
            ...
        }
        ...
    }
    

자바

    public class MainActivity extends Activity {
        ...
        // Instance that returns available files from this app
        private FileUriCallback fileUriCallback;
        ...
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            ...
            // Android Beam file transfer is available, continue
            ...
            nfcAdapter = NfcAdapter.getDefaultAdapter(this);
            /*
             * Instantiate a new FileUriCallback to handle requests for
             * URIs
             */
            fileUriCallback = new FileUriCallback();
            // Set the dynamic callback for URI requests.
            nfcAdapter.setBeamPushUrisCallback(fileUriCallback,this);
            ...
        }
        ...
    }
    

참고: 앱의 NfcAdapter 인스턴스를 통해 Uri 객체의 배열을 NFC 프레임워크에 직접 제공할 수도 있습니다. NFC 터치 이벤트가 발생하기 전에 전송할 URI를 정의할 수 있다면 이 접근 방식을 선택하세요. 이 방식에 관한 자세한 내용은 NfcAdapter.setBeamPushUris()를 참조하세요.

전송할 파일 지정

하나 이상의 파일을 NFC 지원 기기로 전송하려면 각 파일의 파일 URI(file 구성표를 사용하는 URI)를 가져와서 Uri 객체의 배열에 추가합니다. 파일을 전송하려면 영구적인 파일 읽기 권한도 있어야 합니다. 예를 들어, 다음 스니펫은 파일 이름에서 파일 URI를 가져와서 배열에 추가하는 방법을 보여줍니다.

Kotlin

            /*
             * Create a list of URIs, get a File,
             * and set its permissions
             */
            val fileUris = mutableListOf<Uri>()
            val transferFile = "transferimage.jpg"
            val extDir = getExternalFilesDir(null)
            val requestFile = File(extDir, transferFile).apply {
                setReadable(true, false)
            }
            // Get a URI for the File and add it to the list of URIs
            Uri.fromFile(requestFile)?.also { fileUri ->
                fileUris += fileUri
            } ?: Log.e("My Activity", "No File URI available for file.")
    

자바

            /*
             * Create a list of URIs, get a File,
             * and set its permissions
             */
            private Uri[] fileUris = new Uri[10];
            String transferFile = "transferimage.jpg";
            File extDir = getExternalFilesDir(null);
            File requestFile = new File(extDir, transferFile);
            requestFile.setReadable(true, false);
            // Get a URI for the File and add it to the list of URIs
            fileUri = Uri.fromFile(requestFile);
            if (fileUri != null) {
                fileUris[0] = fileUri;
            } else {
                Log.e("My Activity", "No File URI available for file.");
            }
    

관련 추가 정보는 저장소 옵션을 참조하세요.

이 페이지와 관련된 샘플 코드는 Android BeamLargeFiles 샘플을 참조하세요.