1page.title=Requesting a Shared File 2 3trainingnavtop=true 4@jd:body 5 6 7<div id="tb-wrapper"> 8<div id="tb"> 9 10<h2>This lesson teaches you to</h2> 11<ol> 12 <li><a href="#SendRequest">Send a Request for the File</a></li> 13 <li><a href="#OpenFile">Access the Requested File</a> 14</ol> 15 16<h2>You should also read</h2> 17<ul> 18 <li> 19 <a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a> 20 </li> 21 <li> 22 <a href="{@docRoot}guide/topics/providers/content-provider-basics.html#SimpleQuery" 23 >Retrieving Data from the Provider</a> 24 </li> 25</ul> 26 27</div> 28</div> 29 30<p> 31 When an app wants to access a file shared by another app, the requesting app (the client) 32 usually sends a request to the app sharing the files (the server). In most cases, the request 33 starts an {@link android.app.Activity} in the server app that displays the files it can share. 34 The user picks a file, after which the server app returns the file's content URI to the 35 client app. 36</p> 37<p> 38 This lesson shows you how a client app requests a file from a server app, receives the file's 39 content URI from the server app, and opens the file using the content URI. 40</p> 41 42<h2 id="SendRequest">Send a Request for the File</h2> 43<p> 44 To request a file from the server app, the client app calls 45 {@link android.app.Activity#startActivityForResult startActivityForResult} with an 46 {@link android.content.Intent} containing the action such as 47 {@link android.content.Intent#ACTION_PICK ACTION_PICK} and a MIME type that the client app 48 can handle. 49</p> 50<p> 51 For example, the following code snippet demonstrates how to send an 52 {@link android.content.Intent} to a server app in order to start the 53 {@link android.app.Activity} described in <a href="share-file.html#SendURI" 54 >Sharing a File</a>: 55</p> 56<pre> 57public class MainActivity extends Activity { 58 private Intent mRequestFileIntent; 59 private ParcelFileDescriptor mInputPFD; 60 ... 61 @Override 62 protected void onCreate(Bundle savedInstanceState) { 63 super.onCreate(savedInstanceState); 64 setContentView(R.layout.activity_main); 65 mRequestFileIntent = new Intent(Intent.ACTION_PICK); 66 mRequestFileIntent.setType("image/jpg"); 67 ... 68 } 69 ... 70 protected void requestFile() { 71 /** 72 * When the user requests a file, send an Intent to the 73 * server app. 74 * files. 75 */ 76 startActivityForResult(mRequestFileIntent, 0); 77 ... 78 } 79 ... 80} 81</pre> 82<h2 id="OpenFile">Access the Requested File</h2> 83<p> 84 The server app sends the file's content URI back to the client app in an 85 {@link android.content.Intent}. This {@link android.content.Intent} is passed to the client 86 app in its override of {@link android.app.Activity#onActivityResult onActivityResult()}. Once 87 the client app has the file's content URI, it can access the file by getting its 88 {@link java.io.FileDescriptor}. 89</p> 90<p> 91<p> 92 File security is preserved in this process because the content URI is the only piece of data 93 that the client app receives. Since this URI doesn't contain a directory path, the client app 94 can't discover and open any other files in the server app. Only the client app gets access to 95 the file, and only for the permissions granted by the server app. The permissions are temporary, 96 so once the client app's task stack is finished, the file is no longer accessible outside the 97 server app. 98</p> 99<p> 100 The next snippet demonstrates how the client app handles the 101 {@link android.content.Intent} sent from the server app, and how the client app gets the 102 {@link java.io.FileDescriptor} using the content URI: 103</p> 104<pre> 105 /* 106 * When the Activity of the app that hosts files sets a result and calls 107 * finish(), this method is invoked. The returned Intent contains the 108 * content URI of a selected file. The result code indicates if the 109 * selection worked or not. 110 */ 111 @Override 112 public void onActivityResult(int requestCode, int resultCode, 113 Intent returnIntent) { 114 // If the selection didn't work 115 if (resultCode != RESULT_OK) { 116 // Exit without doing anything else 117 return; 118 } else { 119 // Get the file's content URI from the incoming Intent 120 Uri returnUri = returnIntent.getData(); 121 /* 122 * Try to open the file for "read" access using the 123 * returned URI. If the file isn't found, write to the 124 * error log and return. 125 */ 126 try { 127 /* 128 * Get the content resolver instance for this context, and use it 129 * to get a ParcelFileDescriptor for the file. 130 */ 131 mInputPFD = getContentResolver().openFileDescriptor(returnUri, "r"); 132 } catch (FileNotFoundException e) { 133 e.printStackTrace(); 134 Log.e("MainActivity", "File not found."); 135 return; 136 } 137 // Get a regular file descriptor for the file 138 FileDescriptor fd = mInputPFD.getFileDescriptor(); 139 ... 140 } 141 } 142</pre> 143<p> 144 The method {@link android.content.ContentResolver#openFileDescriptor openFileDescriptor()} 145 returns a {@link android.os.ParcelFileDescriptor} for the file. From this object, the client 146 app gets a {@link java.io.FileDescriptor} object, which it can then use to read the file. 147</p> 148