1page.title=Truy cập Thư mục theo Phạm vi
2page.keywords=preview,sdk,scoped directory access
3page.tags=androidn
4
5@jd:body
6
7<div id="qv-wrapper">
8<div id="qv">
9  <h2>Trong tài liệu này</h2>
10  <ol>
11    <li><a href="#accessing">Truy cập một Thư mục lưu trữ bên ngoài</a></li>
12    <li><a href="#removable">Truy cập một Thư mục trên Phương tiện tháo lắp được</a></li>
13    <li><a href="#best">Thực hành Tốt nhất</a></li>
14  </ol>
15</div>
16</div>
17
18<p>Các ứng dụng như ứng dụng ảnh thường chỉ cần truy cập đến các thư mục đã quy định trong
19bộ nhớ ngoài như thư mục <code>Pictures</code>. Các phương pháp
20  hiện tại để truy cập bộ nhớ lưu trữ ngoài vẫn chưa được thiết kế để dễ dàng cho phép
21truy cập thư mục đích cho những kiểu ứng dụng này. Ví dụ:</p>
22
23<ul>
24<li>Việc yêu cầu {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}
25hoặc {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} trong bản kê khai của bạn
26sẽ cho phép truy cập đến tất cả các thư mục công khai trên bộ nhớ lưu trữ ngoài, mà có thể
27cấp nhiều quyền truy cập hơn những gì ứng dụng của bạn cần.</li>
28<li>Sử dụng
29<a href="{@docRoot}guide/topics/providers/document-provider.html">Khuôn khổ
30 Truy cập Kho lưu trữ</a> thường khiến người dùng chọn thư mục
31thông qua UI hệ thống. Đây là điều không cần thiết nếu ứng dụng của bạn luôn truy cập cùng
32một thư mục bên ngoài.</li>
33</ul>
34
35<p>Android N cung cấp một API mới được đơn giản hóa để truy cập
36các thư mục lưu trữ bên ngoài thường dùng. </p>
37
38<h2 id="accessing">Truy cập một Thư mục lưu trữ bên ngoài</h2>
39
40<p>Sử dụng lớp <code>StorageManager</code> để lấy thực thể
41<code>StorageVolume</code> phù hợp. Sau đó tạo một ý định bằng cách gọi phương thức
42<code>StorageVolume.createAccessIntent()</code> của thực thể đó.
43Sử dụng ý định này để truy cập các thư mục lưu trữ bên ngoài. Để lấy danh sách
44tất cả các ổ đĩa, bao gồm các ổ đĩa media có thể tháo lắp, hãy sử dụng
45<code>StorageManager.getVolumesList()</code>.</p>
46
47<p>Đoạn mã sau là một ví dụ về cách mở thư mục
48<code>Pictures</code> trong bộ nhớ lưu trữ chính được chia sẻ:</p>
49
50<pre>
51StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
52StorageVolume volume = sm.getPrimaryVolume();
53Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
54startActivityForResult(intent, request_code);
55</pre>
56
57<p>Hệ thống sẽ cố gắng cấp quyền truy cập tới thư mục bên ngoài và nếu
58cần sẽ xác nhận quyền truy cập với người dùng bằng một UI được đơn giản hóa:</p>
59
60<img src="{@docRoot}preview/images/scoped-folder-access-framed.png" srcset="{@docRoot}preview/images/scoped-folder-access-framed.png 1x,
61{@docRoot}preview/images/scoped-folder-access-framed_2x.png 2x" />
62<p class="img-caption"><strong>Hình 1.</strong> Một ứng dụng yêu cầu
63truy cập tới thư mục Pictures.</p>
64
65<p>Nếu người dùng cấp quyền truy cập, hệ thống sẽ gọi phương thức ghi đè
66<code>onActivityResult()</code> của bạn với mã kết quả là
67<code>Activity.RESULT_OK</code> và dữ liệu ý định có chứa URI. Hãy sử dụng
68URI được cung cấp để truy cập thông tin thư mục, giống như sử dụng các URI
69được trả về bởi
70<a href="{@docRoot}guide/topics/providers/document-provider.html">Khuôn khổ
71 Truy cập Kho lưu trữ</a>.</p>
72
73<p>Nếu người dùng không cấp quyền truy cập, hệ thống sẽ gọi phương thức ghi đè
74<code>onActivityResult()</code> của bạn với mã kết quả là
75<code>Activity.RESULT_CANCELED</code> và dữ liệu ý định có giá trị null.</p>
76
77<p class="note"><b>Lưu ý</b>: Lấy quyền truy cập tới một thư mục bên ngoài được chỉ định
78cũng sẽ cấp quyền truy cập tới các thư mục con thuộc thư mục đó.</p>
79
80<h2 id="removable">Truy cập một Thư mục trên phương tiện tháo lắp được</h2>
81
82<p>Để sử dụng Truy cập Thư mục theo Phạm vi nhằm truy cập các thư mục trên phương tiện có thể tháo lắp,
83trước hết, hãy thêm một {@link android.content.BroadcastReceiver} để lắng nghe
84thông báo {@link android.os.Environment#MEDIA_MOUNTED}, ví dụ:</p>
85
86<pre>
87&lt;receiver
88    android:name=".MediaMountedReceiver"
89    android:enabled="true"
90    android:exported="true" &gt;
91    &lt;intent-filter&gt;
92        &lt;action android:name="android.intent.action.MEDIA_MOUNTED" /&gt;
93        &lt;data android:scheme="file" /&gt;
94    &lt;/intent-filter&gt;
95&lt;/receiver&gt;
96</pre>
97
98<p>Khi người dùng kết nối một phương tiện có thể tháo lắp như thẻ SD thì hệ thống sẽ gửi một thông báo
99{@link android.os.Environment#MEDIA_MOUNTED}. Thông báo này
100sẽ cung cấp một đối tượng <code>StorageVolume</code> trong dữ liệu ý định mà bạn có thể
101sử dụng để truy cập các thư mục trên phương tiện có thể tháo lắp đó. Ví dụ sau
102sẽ truy cập thư mục <code>Pictures</code> trên phương tiện có thể tháo lắp:</p>
103
104<pre>
105// BroadcastReceiver has already cached the MEDIA_MOUNTED
106// notification Intent in mediaMountedIntent
107StorageVolume volume = (StorageVolume)
108    mediaMountedIntent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);
109volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
110startActivityForResult(intent, request_code);
111</pre>
112
113<h2 id="best">Thực hành Tốt nhất</h2>
114
115<p>Khi có thể, hãy duy trì URI truy cập thư mục bên ngoài để bạn không phải
116lặp lại yêu cầu người dùng cấp quyền truy cập. Khi người dùng đã cấp quyền truy cập, hãy gọi
117<code>getContentResolver().takePersistableUriPermssion()</code> với
118URI truy cập thư mục. Hệ thống sẽ duy trì URI và các yêu cầu
119truy cập sau này sẽ trả về <code>RESULT_OK</code> và không hiển thị UI xác nhận cho
120người dùng nữa.</p>
121
122<p>Nếu người dùng từ chối quyền truy cập đến một thư mục bên ngoài thì đừng
123yêu cầu truy cập lại ngay lập tức. Lặp đi lặp lại yêu cầu truy cập sẽ dẫn đến trải nghiệm
124người dùng không tốt.</p>
125