• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.android.apis.content;
18 
19 import android.app.Activity;
20 import android.content.ContentResolver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.database.Cursor;
24 import android.net.Uri;
25 import android.os.Bundle;
26 import android.provider.DocumentsContract;
27 import android.provider.DocumentsContract.Document;
28 import android.util.Log;
29 import android.view.View;
30 import android.view.View.OnClickListener;
31 import android.widget.Button;
32 import android.widget.CheckBox;
33 import android.widget.LinearLayout;
34 import android.widget.ScrollView;
35 import android.widget.TextView;
36 
37 import java.io.ByteArrayOutputStream;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.io.OutputStream;
41 
42 /**
43  * Example that exercises client side of {@link DocumentsContract}.
44  */
45 public class DocumentsSample extends Activity {
46     private static final String TAG = "DocumentsSample";
47 
48     private static final int CODE_READ = 42;
49     private static final int CODE_WRITE = 43;
50     private static final int CODE_TREE = 44;
51     private static final int CODE_RENAME = 45;
52 
53     private TextView mResult;
54 
55     @Override
onCreate(Bundle icicle)56     public void onCreate(Bundle icicle) {
57         super.onCreate(icicle);
58 
59         final Context context = this;
60 
61         final LinearLayout view = new LinearLayout(context);
62         view.setOrientation(LinearLayout.VERTICAL);
63 
64         mResult = new TextView(context);
65         view.addView(mResult);
66 
67         final CheckBox multiple = new CheckBox(context);
68         multiple.setText("ALLOW_MULTIPLE");
69         view.addView(multiple);
70         final CheckBox localOnly = new CheckBox(context);
71         localOnly.setText("LOCAL_ONLY");
72         view.addView(localOnly);
73 
74         Button button;
75         button = new Button(context);
76         button.setText("OPEN_DOC */*");
77         button.setOnClickListener(new OnClickListener() {
78             @Override
79             public void onClick(View v) {
80                 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
81                 intent.addCategory(Intent.CATEGORY_OPENABLE);
82                 intent.setType("*/*");
83                 if (multiple.isChecked()) {
84                     intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
85                 }
86                 if (localOnly.isChecked()) {
87                     intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
88                 }
89                 startActivityForResult(intent, CODE_READ);
90             }
91         });
92         view.addView(button);
93 
94         button = new Button(context);
95         button.setText("OPEN_DOC image/*");
96         button.setOnClickListener(new OnClickListener() {
97             @Override
98             public void onClick(View v) {
99                 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
100                 intent.addCategory(Intent.CATEGORY_OPENABLE);
101                 intent.setType("image/*");
102                 if (multiple.isChecked()) {
103                     intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
104                 }
105                 if (localOnly.isChecked()) {
106                     intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
107                 }
108                 startActivityForResult(intent, CODE_READ);
109             }
110         });
111         view.addView(button);
112 
113         button = new Button(context);
114         button.setText("OPEN_DOC audio/ogg");
115         button.setOnClickListener(new OnClickListener() {
116             @Override
117             public void onClick(View v) {
118                 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
119                 intent.addCategory(Intent.CATEGORY_OPENABLE);
120                 intent.setType("audio/ogg");
121                 if (multiple.isChecked()) {
122                     intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
123                 }
124                 if (localOnly.isChecked()) {
125                     intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
126                 }
127                 startActivityForResult(intent, CODE_READ);
128             }
129         });
130         view.addView(button);
131 
132         button = new Button(context);
133         button.setText("OPEN_DOC text/plain, application/msword");
134         button.setOnClickListener(new OnClickListener() {
135             @Override
136             public void onClick(View v) {
137                 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
138                 intent.addCategory(Intent.CATEGORY_OPENABLE);
139                 intent.setType("*/*");
140                 intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {
141                         "text/plain", "application/msword" });
142                 if (multiple.isChecked()) {
143                     intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
144                 }
145                 if (localOnly.isChecked()) {
146                     intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
147                 }
148                 startActivityForResult(intent, CODE_READ);
149             }
150         });
151         view.addView(button);
152 
153         button = new Button(context);
154         button.setText("CREATE_DOC text/plain");
155         button.setOnClickListener(new OnClickListener() {
156             @Override
157             public void onClick(View v) {
158                 Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
159                 intent.addCategory(Intent.CATEGORY_OPENABLE);
160                 intent.setType("text/plain");
161                 intent.putExtra(Intent.EXTRA_TITLE, "foobar.txt");
162                 if (localOnly.isChecked()) {
163                     intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
164                 }
165                 startActivityForResult(intent, CODE_WRITE);
166             }
167         });
168         view.addView(button);
169 
170         button = new Button(context);
171         button.setText("CREATE_DOC image/png");
172         button.setOnClickListener(new OnClickListener() {
173             @Override
174             public void onClick(View v) {
175                 Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
176                 intent.addCategory(Intent.CATEGORY_OPENABLE);
177                 intent.setType("image/png");
178                 intent.putExtra(Intent.EXTRA_TITLE, "mypicture.png");
179                 if (localOnly.isChecked()) {
180                     intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
181                 }
182                 startActivityForResult(intent, CODE_WRITE);
183             }
184         });
185         view.addView(button);
186 
187         button = new Button(context);
188         button.setText("GET_CONTENT */*");
189         button.setOnClickListener(new OnClickListener() {
190             @Override
191             public void onClick(View v) {
192                 Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
193                 intent.addCategory(Intent.CATEGORY_OPENABLE);
194                 intent.setType("*/*");
195                 if (multiple.isChecked()) {
196                     intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
197                 }
198                 if (localOnly.isChecked()) {
199                     intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
200                 }
201                 startActivityForResult(Intent.createChooser(intent, "Kittens!"), CODE_READ);
202             }
203         });
204         view.addView(button);
205 
206         button = new Button(context);
207         button.setText("OPEN_DOC_TREE");
208         button.setOnClickListener(new OnClickListener() {
209             @Override
210             public void onClick(View v) {
211                 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
212                 if (localOnly.isChecked()) {
213                     intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
214                 }
215                 startActivityForResult(Intent.createChooser(intent, "Kittens!"), CODE_TREE);
216             }
217         });
218         view.addView(button);
219 
220         button = new Button(context);
221         button.setText("OPEN_DOC */* for rename");
222         button.setOnClickListener(new OnClickListener() {
223             @Override
224             public void onClick(View v) {
225                 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
226                 intent.addCategory(Intent.CATEGORY_OPENABLE);
227                 intent.setType("*/*");
228                 startActivityForResult(intent, CODE_RENAME);
229             }
230         });
231         view.addView(button);
232 
233         final ScrollView scroll = new ScrollView(context);
234         scroll.addView(view);
235 
236         setContentView(scroll);
237     }
238 
239     @Override
onActivityResult(int requestCode, int resultCode, Intent data)240     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
241         final ContentResolver cr = getContentResolver();
242 
243         clearLog();
244 
245         log("resultCode=" + resultCode);
246         log("data=" + String.valueOf(data));
247 
248         final Uri uri = data != null ? data.getData() : null;
249         if (uri != null) {
250             log("isDocumentUri=" + DocumentsContract.isDocumentUri(this, uri));
251         } else {
252             log("missing URI?");
253             return;
254         }
255 
256         if (requestCode == CODE_READ) {
257             try {
258                 cr.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
259             } catch (SecurityException e) {
260                 log("FAILED TO TAKE PERMISSION", e);
261             }
262             InputStream is = null;
263             try {
264                 is = cr.openInputStream(uri);
265                 log("read length=" + readFullyNoClose(is).length);
266             } catch (Exception e) {
267                 log("FAILED TO READ", e);
268             } finally {
269                 closeQuietly(is);
270             }
271         } else if (requestCode == CODE_WRITE) {
272             try {
273                 cr.takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
274             } catch (SecurityException e) {
275                 log("FAILED TO TAKE PERMISSION", e);
276             }
277             OutputStream os = null;
278             try {
279                 os = cr.openOutputStream(uri);
280                 os.write("THE COMPLETE WORKS OF SHAKESPEARE".getBytes());
281                 log("wrote data");
282             } catch (Exception e) {
283                 log("FAILED TO WRITE", e);
284             } finally {
285                 closeQuietly(os);
286             }
287         } else if (requestCode == CODE_TREE) {
288             // Find existing docs
289             Uri doc = DocumentsContract.buildDocumentUriUsingTree(uri,
290                     DocumentsContract.getTreeDocumentId(uri));
291             Uri child = DocumentsContract.buildChildDocumentsUriUsingTree(uri,
292                     DocumentsContract.getTreeDocumentId(uri));
293             Cursor c = cr.query(child, new String[] {
294                     Document.COLUMN_DISPLAY_NAME, Document.COLUMN_MIME_TYPE }, null, null, null);
295             try {
296                 while (c.moveToNext()) {
297                     log("found child=" + c.getString(0) + ", mime=" + c.getString(1));
298                 }
299             } finally {
300                 closeQuietly(c);
301             }
302 
303             // Create some documents
304             Uri pic = DocumentsContract.createDocument(cr, doc, "image/png", "pic.png");
305             Uri dir = DocumentsContract.createDocument(cr, doc, Document.MIME_TYPE_DIR, "my dir");
306             Uri dirPic = DocumentsContract.createDocument(cr, dir, "image/png", "pic2.png");
307 
308             log("created " + pic);
309             log("created " + dir);
310             log("created " + dirPic);
311 
312             // Write to one of them
313             OutputStream os = null;
314             try {
315                 os = cr.openOutputStream(dirPic);
316                 os.write("THE COMPLETE WORKS OF SHAKESPEARE".getBytes());
317                 log("wrote data");
318             } catch (Exception e) {
319                 log("FAILED TO WRITE", e);
320             } finally {
321                 closeQuietly(os);
322             }
323 
324             // And delete the first pic
325             if (DocumentsContract.deleteDocument(cr, pic)) {
326                 log("deleted untouched pic");
327             } else {
328                 log("FAILED TO DELETE PIC");
329             }
330         } else if (requestCode == CODE_RENAME) {
331             final Uri newUri = DocumentsContract.renameDocument(cr, uri, "MEOW.TEST");
332             log("rename result=" + newUri);
333 
334             InputStream is = null;
335             try {
336                 is = cr.openInputStream(newUri);
337                 log("read length=" + readFullyNoClose(is).length);
338             } catch (Exception e) {
339                 log("FAILED TO READ", e);
340             } finally {
341                 closeQuietly(is);
342             }
343         }
344     }
345 
clearLog()346     private void clearLog() {
347         mResult.setText(null);
348     }
349 
log(String msg)350     private void log(String msg) {
351         log(msg, null);
352     }
353 
log(String msg, Throwable t)354     private void log(String msg, Throwable t) {
355         Log.d(TAG, msg, t);
356         mResult.setText(mResult.getText() + "\n" + msg);
357     }
358 
readFullyNoClose(InputStream in)359     public static byte[] readFullyNoClose(InputStream in) throws IOException {
360         ByteArrayOutputStream bytes = new ByteArrayOutputStream();
361         byte[] buffer = new byte[1024];
362         int count;
363         while ((count = in.read(buffer)) != -1) {
364             bytes.write(buffer, 0, count);
365         }
366         return bytes.toByteArray();
367     }
368 
closeQuietly(AutoCloseable closeable)369     public static void closeQuietly(AutoCloseable closeable) {
370         if (closeable != null) {
371             try {
372                 closeable.close();
373             } catch (RuntimeException rethrown) {
374                 throw rethrown;
375             } catch (Exception ignored) {
376             }
377         }
378     }
379 }
380