Slide 1

Slide 1 text

Document-centric Android Droidcon Berlin 2015

Slide 2

Slide 2 text

Overview ● Storage Access Framework ● Document-centric Overview Screen

Slide 3

Slide 3 text

Storage Access Framework ● framework to browse and open documents, images, and other files across preferred document storage providers ● standard, easy-to-use UI to let users access documents in a consistent way across apps

Slide 4

Slide 4 text

Getting content the hard way Custom file picker

Slide 5

Slide 5 text

Getting content the hard way Custom file picker

Slide 6

Slide 6 text

Getting content the hard way Custom file picker

Slide 7

Slide 7 text

Getting content the old way ACTION_GET_CONTENT before the introduction of the Storage Access Framework

Slide 8

Slide 8 text

Getting content the “new” way Android 4.4+ ● Document Providers at the top ● “Legacy” providers at the bottom

Slide 9

Slide 9 text

SAF User Interface

Slide 10

Slide 10 text

SAF User Interface

Slide 11

Slide 11 text

SAF User Interface

Slide 12

Slide 12 text

SAF User Interface

Slide 13

Slide 13 text

Getting content Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); intent.addCategory(Intent.CATEGORY_OPENABLE); Intent chooserIntent = Intent.createChooser(i, null); startActivityForResult(chooserIntent, requestCode);

Slide 14

Slide 14 text

Getting content Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); Intent chooserIntent = Intent.createChooser(i, null); startActivityForResult(chooserIntent, requestCode); intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

Slide 15

Slide 15 text

Getting content - onActivityResult if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { ClipData clipData = data.getClipData(); if (clipData != null) { // read URIs from ClipData return; } } // read URI from Intent.getData()

Slide 16

Slide 16 text

Options for saving content ● Download Manager ● Share Intent ● Write to hardcoded directories ● …

Slide 17

Slide 17 text

Picking a directory Use third-party app to select directory

Slide 18

Slide 18 text

Picking a directory Use third-party app to select directory private static final String[][] PICK_DIRECTORY_INTENTS = { { "org.openintents.action.PICK_DIRECTORY", "file://" }, { "com.estrongs.action.PICK_DIRECTORY", "file://" }, { Intent.ACTION_PICK, "folder://" }, { "com.androidworkz.action.PICK_DIRECTORY", "file://" } };

Slide 19

Slide 19 text

Saving content the hard way Custom UI ● Cloud providers need to be supported by the app

Slide 20

Slide 20 text

Saving content the new way ACTION_CREATE_DOCUMENT

Slide 21

Slide 21 text

Saving content the new way Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); intent.setType("image/jpeg"); intent.putExtra(Intent.EXTRA_TITLE, "corgi.jpg"); intent.addCategory(Intent.CATEGORY_OPENABLE); startActivityForResult(intent, requestCode);

Slide 22

Slide 22 text

Picking a directory the new way Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); startActivityForResult(intent, requestCode); // in onActivityResult - receive URI for document tree String rootDocumentId = DocumentsContract.getTreeDocumentId(treeUri); Uri rootDocumentUri = DocumentsContract.buildDocumentUriUsingTree( treeUri, rootDocumentId); Uri newDocumentUri = DocumentsContract.createDocument( contentResolver, rootDocumentUri, "image/png", "new.png");

Slide 23

Slide 23 text

Picking a directory the new way ACTION_OPEN_DOCUMENT_TREE Not even implemented by the Google Drive app :(

Slide 24

Slide 24 text

Overview Screen ● Introduced with Android 5.0 ● Previously app-centric Recent Apps Screen

Slide 25

Slide 25 text

App-centric world Recent Apps one entry per app

Slide 26

Slide 26 text

Document-centric world Overview Screen one entry per document

Slide 27

Slide 27 text

How to create a new document task? Ideally, it just works Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("mailto:[email protected]")); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); startActivity(intent);

Slide 28

Slide 28 text

How to create a new document task? Ideally, it just works Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("mailto:[email protected]")); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); startActivity(intent); Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET

Slide 29

Slide 29 text

How to create a new document task? Ideally, it just works Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("mailto:[email protected]")); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); startActivity(intent); Intent.FLAG_ACTIVITY_NEW_DOCUMENT

Slide 30

Slide 30 text

When to use FLAG_ACTIVITY_NEW_DOCUMENT? ● Potentially whenever starting an external activity ● When multiple entries for your app in the Overview Screen are desirable

Slide 31

Slide 31 text

More Activity Flags ● With FLAG_ACTIVITY_NEW_DOCUMENT existing tasks will be brought to the front ● Use FLAG_ACTIVITY_MULTIPLE_TASK to force creation of a new task

Slide 32

Slide 32 text

documentLaunchMode ● always ● intoExisting ● never ● none Use this rather than the Intent flag! attribute in manifest

Slide 33

Slide 33 text

TaskDescription

Slide 34

Slide 34 text

TaskDescription TaskDescription taskDescription = new TaskDescription(title, icon, Color.DKGRAY); setTaskDescription(taskDescription);

Slide 35

Slide 35 text

Manage document tasks ● Activity.finishAndRemoveTask() ● ActivityManager.getAppTasks() ○ finishAndRemoveTask() ○ moveToFront() ○ startActivity(…) ○ getTaskInfo().baseIntent ○ …

Slide 36

Slide 36 text

makeTaskLaunchBehind Document tasks are grouped when makeTaskLaunchBehind is used

Slide 37

Slide 37 text

makeTaskLaunchBehind Intent newDocumentIntent = …; ActivityOptions options = ActivityOptions.makeTaskLaunchBehind(); startActivity(newDocumentIntent, options.toBundle());

Slide 38

Slide 38 text

persistableMode attribute in manifest ● persistRootOnly (default) ● persistNever ● persistAcrossReboots ○ PeristableBundle

Slide 39

Slide 39 text

Summary ● SAF makes many things easier ○ Not a solution for pre-KitKat devices ○ Support isn’t great right now :( ● Document tasks solve many small issues ● It’s easy to get started. Do it now!

Slide 40

Slide 40 text

Thank you! Questions?

Slide 41

Slide 41 text

Bonus slide: Corgis CC BY-SA 2.0 Source: https://flic.kr/p/dZrnNm

Slide 42

Slide 42 text

Further questions? Email: [email protected] Google+: +cketti