Upgrade to Pro — share decks privately, control downloads, hide ads and more …

You don't need the Storage Permission

19f33af017093834caecee97856322e6?s=47 cketti
February 22, 2017

You don't need the Storage Permission

Talk given at the Berlindroid Meetup in February 2017



February 22, 2017

More Decks by cketti

Other Decks in Programming


  1. You don’t need the Storage Permission* cketti Berlindroid Meetup -

    February 2017
  2. Disclaimer • Heavily based on Ian Lake’s talk Forget the

    Storage Permission: Alternatives for sharing and collaborating from Big Android BBQ 2015
  3. Storage? What storage? • App-specific private directories • App-specific public

    external directories • Public storage
  4. App-specific private directories • Context.getFilesDir() • Context.getCacheDir() No storage permission

  5. App-specific public external directories • Context.getExternalFilesDir() • Context.getExternalCacheDir() • Context.getExternalMediaDirs()

    No storage permission required on API 19+
  6. Public storage User public “external” storage directory • Environment.getExternalStorageDirectory() •

    Environment.getExternalStoragePublicDirectory(String) Storage permission required
  7. Storage permission required? < API 19 API 19-22 API 23+

    App internal No No No App external Yes No* No* User external Yes Yes Yes * Only for your own app
  8. maxSdkVersion <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="18" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" />

  9. Life without storage permission Common cases for requesting the storage

    permission: • Reading content • Saving content • Sharing content • Receiving content
  10. ACTION_GET_CONTENT Before API 19 API 19+

  11. Storage Access Framework UI

  12. ACTION_GET_CONTENT result From the documentation: Output: The URI of the

    item that was picked. This must be a content: URI so that any receiver can access it. Use ContentResolver.openInputStream(Uri) to access the content.
  13. ACTION_OPEN_DOCUMENT Like ACTION_GET_CONTENT, but without the support for legacy apps

    All returned Uris support persistable permissions using ContentResolver.takePersistableUriPermission() API 21+: ACTION_OPEN_DOCUMENT_TREE
  14. ACTION_CREATE_DOCUMENT Specify type and initial “display name” in Intent Use

    Storage Access Framework to select where to create the file Open URI for writing using ContentResolver.openOutputStream() or ContentResolver.openFileDescriptor() Supports persisting URI permissions
  15. ACTION_SEND EXTRA_STREAM contains Uri that points to the content (use

    FileProvider) FLAG_GRANT_READ_URI_PERMISSION grants receiving app permission to access this Uri But URI permissions weren’t well understood in the early days -> People used file:// URIs :(
  16. URI-based permissions Flags added to Intent • Intent.FLAG_GRANT_READ_URI_PERMISSION • Intent.FLAG_GRANT_WRITE_URI_PERMISSION

    Granted/revoked programmatically • Context.grantUriPermission() • Context.revokeUriPermission()
  17. Intent + FLAG_GRANT_*_URI_PERMISSION Flag only affects Uris in the data

    and clipData fields of an Intent Framework contains special handling for ACTION_SEND: Copies contents of EXTRA_STREAM extra to clipData field ClipData is API 16+ Workaround <API 16: Set data field to value of EXTRA_STREAM extra
  18. Receiving content Receive Intent with content:// URI + FLAG_GRANT_READ_URI_PERMISSION We

    only have permission to access the content as long as the receiving component (usually Activity) is alive Permission grant can be passed on to other components, also other apps -> Intent + FLAG_GRANT_READ_URI_PERMISSION
  19. MediaStore.ACTION_*_CAPTURE EXTRA_OUTPUT contains URI where the content will be written

    to Same issues as ACTION_SEND; URI permissions don’t apply to EXTRA_OUTPUT Framework only added special handling for this with API 21 Workaround: Set data and/or clipData field to content: URI
  20. Recap Storage Permission Internal app-specific storage no External app-specific storage

    maxSdkVersion=”18” ACTION_GET_CONTENT no* ACTION_*_DOCUMENT no Sending files with ACTION_SEND no Receiving files no* * If you want to support misbehaving apps: maxSdkVersion=”22”
  21. FileUriExposedException The exception that is thrown when an application exposes

    a file:// Uri to another app. Only affects apps with targetSdkVersion 24+. Use of file:// Uri is still discouraged.
  22. Thanks! Questions? Email: hello@cketti.de Twitter: @cketti