| page.title=Requesting a Shared File | |
| trainingnavtop=true | |
| @jd:body | |
| <div id="tb-wrapper"> | |
| <div id="tb"> | |
| <h2>This lesson teaches you to</h2> | |
| <ol> | |
| <li><a href="#SendRequest">Send a Request for the File</a></li> | |
| <li><a href="#OpenFile">Access the Requested File</a> | |
| </ol> | |
| <h2>You should also read</h2> | |
| <ul> | |
| <li> | |
| <a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a> | |
| </li> | |
| <li> | |
| <a href="{@docRoot}guide/topics/providers/content-provider-basics.html#SimpleQuery" | |
| >Retrieving Data from the Provider</a> | |
| </li> | |
| </ul> | |
| </div> | |
| </div> | |
| <p> | |
| When an app wants to access a file shared by another app, the requesting app (the client) | |
| usually sends a request to the app sharing the files (the server). In most cases, the request | |
| starts an {@link android.app.Activity} in the server app that displays the files it can share. | |
| The user picks a file, after which the server app returns the file's content URI to the | |
| client app. | |
| </p> | |
| <p> | |
| This lesson shows you how a client app requests a file from a server app, receives the file's | |
| content URI from the server app, and opens the file using the content URI. | |
| </p> | |
| <h2 id="SendRequest">Send a Request for the File</h2> | |
| <p> | |
| To request a file from the server app, the client app calls | |
| {@link android.app.Activity#startActivityForResult startActivityForResult} with an | |
| {@link android.content.Intent} containing the action such as | |
| {@link android.content.Intent#ACTION_PICK ACTION_PICK} and a MIME type that the client app | |
| can handle. | |
| </p> | |
| <p> | |
| For example, the following code snippet demonstrates how to send an | |
| {@link android.content.Intent} to a server app in order to start the | |
| {@link android.app.Activity} described in <a href="share-file.html#SendURI" | |
| >Sharing a File</a>: | |
| </p> | |
| <pre> | |
| public class MainActivity extends Activity { | |
| private Intent mRequestFileIntent; | |
| private ParcelFileDescriptor mInputPFD; | |
| ... | |
| @Override | |
| protected void onCreate(Bundle savedInstanceState) { | |
| super.onCreate(savedInstanceState); | |
| setContentView(R.layout.activity_main); | |
| mRequestFileIntent = new Intent(Intent.ACTION_PICK); | |
| mRequestFileIntent.setType("image/jpg"); | |
| ... | |
| } | |
| ... | |
| protected void requestFile() { | |
| /** | |
| * When the user requests a file, send an Intent to the | |
| * server app. | |
| * files. | |
| */ | |
| startActivityForResult(mRequestFileIntent, 0); | |
| ... | |
| } | |
| ... | |
| } | |
| </pre> | |
| <h2 id="OpenFile">Access the Requested File</h2> | |
| <p> | |
| The server app sends the file's content URI back to the client app in an | |
| {@link android.content.Intent}. This {@link android.content.Intent} is passed to the client | |
| app in its override of {@link android.app.Activity#onActivityResult onActivityResult()}. Once | |
| the client app has the file's content URI, it can access the file by getting its | |
| {@link java.io.FileDescriptor}. | |
| </p> | |
| <p> | |
| <p> | |
| File security is preserved in this process because the content URI is the only piece of data | |
| that the client app receives. Since this URI doesn't contain a directory path, the client app | |
| can't discover and open any other files in the server app. Only the client app gets access to | |
| the file, and only for the permissions granted by the server app. The permissions are temporary, | |
| so once the client app's task stack is finished, the file is no longer accessible outside the | |
| server app. | |
| </p> | |
| <p> | |
| The next snippet demonstrates how the client app handles the | |
| {@link android.content.Intent} sent from the server app, and how the client app gets the | |
| {@link java.io.FileDescriptor} using the content URI: | |
| </p> | |
| <pre> | |
| /* | |
| * 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. | |
| */ | |
| mInputPFD = 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 = mInputPFD.getFileDescriptor(); | |
| ... | |
| } | |
| } | |
| </pre> | |
| <p> | |
| The method {@link android.content.ContentResolver#openFileDescriptor openFileDescriptor()} | |
| returns a {@link android.os.ParcelFileDescriptor} for the file. From this object, the client | |
| app gets a {@link java.io.FileDescriptor} object, which it can then use to read the file. | |
| </p> |