Home | History | Annotate | Download | only in secure-file-sharing
      1 page.title=Requesting a Shared File
      2 
      3 trainingnavtop=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>
     57 public class MainActivity extends Activity {
     58     private Intent mRequestFileIntent;
     59     private ParcelFileDescriptor mInputPFD;
     60     ...
     61     &#64;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     &#64;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