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

공유 파일 요청

앱이 다른 앱에서 공유한 파일에 액세스하려 하면 일반적으로 요청 앱(클라이언트)은 파일을 공유하는 앱(서버)에 요청을 전송합니다. 대부분의 경우 요청은 공유할 수 있는 파일을 표시하는 서버 앱에서 Activity를 시작합니다. 사용자가 파일을 선택하고 나면 서버 앱에서는 파일의 콘텐츠 URI를 클라이언트 앱에 반환합니다.

이 과정에서는 클라이언트 앱이 서버 앱의 파일을 요청하고 서버 앱에서 파일의 콘텐츠 URI를 수신한 후 콘텐츠 URI를 사용하여 파일을 여는 방법을 안내합니다.

파일 요청 전송

서버 앱의 파일을 요청하기 위해 클라이언트 앱은 ACTION_PICK과 같은 작업 및 클라이언트 앱에서 처리할 수 있는 MIME 유형이 포함된 IntentstartActivityForResult를 호출합니다.

예를 들어 다음 코드 스니펫에서는 파일 공유에 설명된 Activity를 시작하기 위해 Intent를 서버 앱으로 전송하는 방법을 보여줍니다.

Kotlin

    class MainActivity : Activity() {
        private lateinit var requestFileIntent: Intent
        private lateinit var inputPFD: ParcelFileDescriptor
        ...
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            requestFileIntent = Intent(Intent.ACTION_PICK).apply {
                type = "image/jpg"
            }
            ...
        }
        ...
        private fun requestFile() {
            /**
             * When the user requests a file, send an Intent to the
             * server app.
             * files.
             */
            startActivityForResult(requestFileIntent, 0)
            ...
        }
        ...
    }
    

자바

    public class MainActivity extends Activity {
        private Intent requestFileIntent;
        private ParcelFileDescriptor inputPFD;
        ...
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            requestFileIntent = new Intent(Intent.ACTION_PICK);
            requestFileIntent.setType("image/jpg");
            ...
        }
        ...
        protected void requestFile() {
            /**
             * When the user requests a file, send an Intent to the
             * server app.
             * files.
             */
                startActivityForResult(requestFileIntent, 0);
            ...
        }
        ...
    }
    

요청한 파일에 액세스

서버 앱은 파일의 콘텐츠 URI를 Intent의 클라이언트 앱으로 다시 보냅니다. 이 IntentonActivityResult()의 재정의에서 클라이언트 앱으로 전달됩니다. 클라이언트 앱에 파일의 콘텐츠 URI가 있으면 이 클라이언트 앱은 FileDescriptor를 가져와 파일에 액세스할 수 있습니다.

콘텐츠 URI가 클라이언트 앱에서 수신하는 유일한 데이터이므로 이 프로세스에서는 파일 보안이 유지됩니다. 이 URI는 디렉터리 경로를 포함하지 않으므로 클라이언트 앱은 서버 앱의 다른 파일을 검색하여 열 수 없습니다. 클라이언트 앱만 파일에 액세스할 수 있으며 서버 앱이 부여한 권한으로만 액세스할 수 있습니다. 권한은 일시적이므로 클라이언트 앱의 작업 스택이 완료되면 서버 앱 외부에서 파일에 더 이상 액세스할 수 없습니다.

다음 스니펫에서는 클라이언트 앱이 서버 앱에서 전송한 Intent를 처리하는 방법 및 클라이언트 앱이 콘텐츠 URI를 사용하여 FileDescriptor를 가져오는 방법을 보여줍니다.

Kotlin

    /*
     * When the Activity of the app that hosts files sets a result and calls
     * finish(), this method is invoked. The returned Intent contains the
     * content URI of a selected file. The result code indicates if the
     * selection worked or not.
     */
    public override fun onActivityResult(requestCode: Int, resultCode: Int, returnIntent: Intent) {
        // If the selection didn't work
        if (resultCode != Activity.RESULT_OK) {
            // Exit without doing anything else
            return
        }
        // Get the file's content URI from the incoming Intent
        returnIntent.data?.also { returnUri ->
            /*
             * Try to open the file for "read" access using the
             * returned URI. If the file isn't found, write to the
             * error log and return.
             */
            inputPFD = try {
                /*
                 * Get the content resolver instance for this context, and use it
                 * to get a ParcelFileDescriptor for the file.
                 */
                contentResolver.openFileDescriptor(returnUri, "r")
            } catch (e: FileNotFoundException) {
                e.printStackTrace()
                Log.e("MainActivity", "File not found.")
                return
            }

            // Get a regular file descriptor for the file
            val fd = inputPFD.fileDescriptor
            ...
        }
    }
    

자바

        /*
         * When the Activity of the app that hosts files sets a result and calls
         * finish(), this method is invoked. The returned Intent contains the
         * content URI of a selected file. The result code indicates if the
         * selection worked or not.
         */
        @Override
        public void onActivityResult(int requestCode, int resultCode,
                Intent returnIntent) {
            // If the selection didn't work
            if (resultCode != RESULT_OK) {
                // Exit without doing anything else
                return;
            } else {
                // Get the file's content URI from the incoming Intent
                Uri returnUri = returnIntent.getData();
                /*
                 * Try to open the file for "read" access using the
                 * returned URI. If the file isn't found, write to the
                 * error log and return.
                 */
                try {
                    /*
                     * Get the content resolver instance for this context, and use it
                     * to get a ParcelFileDescriptor for the file.
                     */
                    inputPFD = getContentResolver().openFileDescriptor(returnUri, "r");
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                    Log.e("MainActivity", "File not found.");
                    return;
                }
                // Get a regular file descriptor for the file
                FileDescriptor fd = inputPFD.getFileDescriptor();
                ...
            }
        }
    

openFileDescriptor() 메서드는 파일의 ParcelFileDescriptor를 반환합니다. 클라이언트 앱은 이 객체에서 FileDescriptor 객체를 가져와서 나중에 파일을 읽는 데 사용할 수 있습니다.

추가 관련 정보는 다음을 참조하세요.