[Android][Lollipop]Android5.0에서 가능한 SD 카드로 쓰기 시도

이 기사는 안드로이드 5입니다.0에 SD카드 쓰기에 자유롭게 접근할 수 있는 방법이 추가되었기 때문에 다음은 Stackoverflow의 총결산입니다.
  • How to use the new SD-Card access API presented for Lollipop?
  • 이런 뉴스를 계기로
  • Android 5.0(Lolipop)은 SD 카드와 같은 외부 스토리지에 쓰기 작업을 다시 지원합니다.
  • 권한에 대한 언급이 정확하지 않아서 사용하고 싶어서 사용해 보았습니다.
    ES File Resource Manager에서 확실히 구현되었습니다!

    Android SD 카드 액세스


    아시다시피 4.3 이전에 발표WRITE_EXTERNAL_STORAGE하면 SD카드와 무언가에 자유롭게 접근할 수 있습니다.
    SD카드가 어디 있냐는 함정도 있어요. 지금도 그래요?
    Google의 큰 방침인 SD카드는 External Storage를 방문하더라도 추천하지 않을 것 같습니다.
    그러나 4.4Kitkat은 SD 카드에 대한 액세스를 제한했습니다.
  • 앞으로 KitKat 터미널은 응용 프로그램에서 마이크로소프트 SD 카드에 쓸 수 있을 것이다
  • 그러나 Storage Access Framework를 사용하여 사용자에게 명시적으로 허가를 받은 경우 세션 간에 쓰거나 변경할 수 있습니다.
    상세한 상황document과 이 보도는 이해하기 쉽다.
  • Storage Access Framework 를 사용해 보십시오!
  • Android4.4 Storage Access Framework 설명
  • Kitkat의 Storage Access Framework(SAF) 사용 방법 개요


    Storage Access Framework
  • 투수
  • 를 통해 사용자에게 파일에 접근할 수 있도록 요청한다.
  • 자신이 응용한 저장소(예를 들어 클라우드 저장소)를 관리할 수 있는 Docoment Provider에 접근할 수 있도록 하고 다른 응용 프로그램에서 편집할 수 있는 중심의 Provider를 허용한다.
  • 두 가지 기능이 있습니다.
    SD 카드에 액세스하려면 첫 번째 투수를 통해 허가를 받은 후 편집하십시오.
    MyFragment.java
    // IntentでProviderを実装している呼びます。
    public void performFileSearch() {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        // Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
        // 適宜ピッカー表示の際のフィルターを追加
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("image/*");
        startActivityForResult(intent, READ_REQUEST_CODE);
    }
    
    @Override
    public void onActivityResult(int requestCode, int resultCode,
            Intent resultData) {
        // ピッカーで受け取った結果で色々行います。
        if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            Uri uri = null;
            if (resultData != null) {
                uri = resultData.getData();
                Log.i(TAG, "Uri: " + uri.toString());
                showImage(uri);
            }
        }
    }
    
    이 예는 미디어스토어를 통한 방문과 다를 것이 없지만 언론뿐만 아니라 방문할 수 있는 좋은 곳이다.

    Lolipop으로 배운 거.


    다만 SAF가 확장됐을 뿐 실제 내용과 키트캣 때는 거의 변화가 없었다.
    문서 응용 프로그램을 호출하는 intent에 ACTION_OPEN_DOCUMENT_TREE 추가되었습니다.
    그러나 Directory 이하의 쓰기 권한이 허용되며, SD 카드 이하의 액세스 권한이 사용자에게 부여되면 Android 4가 사용됩니다.3 이하의 동일한 방문이 가능하다.
    또 영구적으로 접근권도 줄 수 있기 때문에 SD카드 이하 접근이 허용되면 이후 확인을 위한 투수는 들어갈 수 없다는 입장이다.
    키트캣도 상시적인 접근 권한을 유지하지만, 파일마다 권한이 달라 결과적으로 매번 투수를 보여줘야 한다는 점이 중요하다.

    설치 예


    설치 방법은 Kitkat과 다릅니다.
    위의 예에서 Intent의 Action은 OPEN입니다.DOCUMENT_TREE로 전환하여 onActivity Result에서 허가를 받은 후 Permission을 보류합니다.
    (위의 예도 유지할 수 있다.)
    MyFragment.java
    public void requestSdcardAccessPermission() {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
        startActivityForResult(intent, REQUEST_CODE);
    }
    
    Action 컨텐츠 열기DOCUMENT_TREE로 변경합니다.
    MyFragment.java
    
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
        if (resultCode == Activity.RESULT_OK) {
            // IntentからtreeのURIを取得します。
            Uri treeUri = resultData.getData();
    
            DocumentFile pickedDir = DocumentFile.fromTreeUri(getActivity(), treeUri);
            // この間は自由にアクセスできるので、treeのリストなどを表示できます。
            // List all existing files inside picked directory
            for (DocumentFile file : pickedDir.listFiles()) {
                LogUtil.d(TAG, "Found file " + file.getName() + " with size " + file.length());
            }
    
    아까처럼 Intent에서 tree의 URI를 얻었습니다.
    이 Uri는 유효 기간 동안 자유롭게 접근할 수 있기 때문에tree 목록 등을 표시할 수 있습니다.
    MyFragment.java
    
            // 恒常的にPermissionを取得するにはContentResolverでtakePersistableUriPermissionを呼び出します。
            getActivity().getContentResolver().takePersistableUriPermission(treeUri,
                        Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    
    
    URI의 Permission을 영구적으로 얻으려면 Content Resolver에서 tak ePerstable UriPermission을 호출하십시오.
    또한 나중에 액세스하기 위해서는 이 시점의 URI를 기억해야 합니다.
    MyFragment.java
            // JavaのFileを扱うように自由に書き込みもできます。
            // ただしSAFのAPIを介する必要があります。
            // また、一度付与されたuriは保持しておく必要があります。
            // Create a new file and write into it
            DocumentFile newFile = pickedDir.createFile("text/plain", "My Novel");
            try {
                OutputStream out = getActivity().getContentResolver().openOutputStream(newFile.getUri());
                out.write("A long time ago...".getBytes());
                out.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    SAF의 API를 통해 IOStrem 등 Java의 API로 변환해 자유롭게 쓸 수 있다.
    SAF의 API(DocumentsContract 등)를 사용하고 여기에는 SupportLibraryDocumentFile를 사용하여 액세스할 수 있습니다.
    java
    // preferenceなどに保存しておいたURiを取り出します。
    Uri treeUri = PreferenceUtil.getSharedPreferenceUri();
    
    // SDカードのdocumentを作成します。
    DocumentFile sdcard = DocumentFile.fromTreeUri(mContext, treeUri);
    // そこからファイルをたどっていく必要があります。
    DocumentFile nextDocument = document.findFile("test");
    :
    
    // APIを通じてIOStreamを作りたいときはDocumentFileを使うと便利です。
    DocumentFile targetDocument = getDocumentFile(file, false);
    OutputStream outStream = Application.getAppContext().
        getContentResolver().openOutputStream(targetDocument.getUri());
    
    

    총결산·주의사항


    요약 고려 사항
  • 사용자가 UI를 통해 특정 디렉토리(모두 SD 전체)에 대한 액세스를 한 번에 지정해야 합니다.(난 허들 높이가 높은 것 같아)
  • URI 사전 기록 필요
  • 일반적인 File과 다른 API에 액세스해야 합니다.
  • 기다려요.
    응, 그럴 수 있지만 귀찮아지지 않을 거라는 걸 알 수 있을 것 같아.
    ES File Resource Manager는 지침을 통해 간단명료하게 설명하므로 매우 유용하다고 생각합니다.

    좋은 웹페이지 즐겨찾기