1# 开发用户文件管理器(仅对系统应用开放)
2
3OpenHarmony预置了FileManager文件管理器。系统应用开发者也可以根据需要,按以下指导自行开发文件管理器。
4
5## 开发步骤
6开发用户文件管理器的相关API详细介绍请参见[API参考](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md)。
7
81. 权限配置和导入模块。
9   申请ohos.permission.FILE_ACCESS_MANAGERohos.permission.GET_BUNDLE_INFO_PRIVILEGED权限,配置方式请参见[申请应用权限](../security/AccessToken/determine-application-mode.md#system_basic等级应用申请权限的方式)。
10
11   > **说明:**
12   >
13   > ohos.permission.FILE_ACCESS_MANAGER是使用文件访问框架接口的基础权限。
14   >
15   > ohos.permission.GET_BUNDLE_INFO_PRIVILEGED权限可以用于查询系统内当前支持的文件管理服务端应用信息。
16
172. 导入依赖模块。
18
19   ```ts
20   import { fileAccess } from '@kit.CoreFileKit';
21   import { fileExtensionInfo } from '@kit.CoreFileKit';
22   ```
23
24   其中fileAccess提供了文件基础操作的API,fileExtensionInfo提供了应用开发的关键结构体。
25
263. 查询设备列表。
27   开发者可以获取当前系统所有文件管理服务端管理的设备属性,也可以获取某个文件管理服务端管理的设备属性。应用开发者可以按需过滤设备。
28
29   在文件访问框架中,使用RootInfo用于表示设备的属性信息。以下示例可以获取所有设备的RootInfo。
30
31   ```ts
32   import { common } from '@kit.AbilityKit';
33   import { BusinessError } from '@kit.BasicServicesKit';
34   import { Filter } from '@kit.CoreFileKit';
35
36   // 获取应用上下文
37   let context = getContext(this) as common.UIAbilityContext;
38
39   // 创建连接系统内所有文件管理服务端的helper对象
40   let fileAccessHelperAllServer: fileAccess.FileAccessHelper;
41   function createFileAccessHelper(): void {
42     try {    // this.context是EntryAbility传过来的Context
43       fileAccessHelperAllServer = fileAccess.createFileAccessHelper(context);
44       if (!fileAccessHelperAllServer) {
45         console.error("createFileAccessHelper interface returns an undefined object");
46       }
47     } catch (err) {
48         let error: BusinessError = err as BusinessError;
49         console.error("createFileAccessHelper failed, errCode:" + error.code + ", errMessage:" + error.message);
50     }
51   }
52   let rootInfos: Array<fileAccess.RootInfo> = [];
53   async function getRoots(): Promise<void>{
54     let rootIterator: fileAccess.RootIterator;
55     let isDone: boolean = false;
56     try {
57       rootIterator = await fileAccessHelperAllServer.getRoots();
58       if (!rootIterator) {
59         console.error("getRoots interface returns an undefined object");
60         return;
61       }
62       while (!isDone) {
63         let result = rootIterator.next();
64         console.info("next result = " + JSON.stringify(result));
65         isDone = result.done;
66         if (!isDone)
67           rootInfos.push(result.value);
68       }
69     } catch (err) {
70       let error: BusinessError = err as BusinessError;
71       console.error("getRoots failed, errCode:" + error.code + ", errMessage:" + error.message);
72     }
73   }
74   ```
75
764. 浏览目录。
77   在文件访问框架中,使用FileInfo表示一个文件(目录)的基础信息。开发者可以使用listfile接口遍历下一级所有文件(目录)的迭代器对象;也可以通过scanfile过滤指定目录,获取满足条件的迭代器对象。
78
79    listfile和scanfile接口当前支持RootInfo对象调用,可用于支撑遍历下一级文件或过滤整个目录树。同时,接口也支持FileInfo对象调用,用于支撑遍历下一级文件或过滤指定目录。
80
81   ```ts
82   import { BusinessError } from '@kit.BasicServicesKit';
83   import { Filter } from '@kit.CoreFileKit';
84
85   // 从根目录开始
86   let rootInfos = [];
87   //rootInfos 从getRoots()获取
88   let rootInfo: fileAccess.RootInfo = rootInfos[0];
89   let fileInfos: Array<fileAccess.FileInfo> = [];
90   let isDone: boolean = false;
91   let filter: Filter = {suffix : [".txt", ".jpg", ".xlsx"]}; // 设定过滤条件
92   try {
93     let fileIterator = rootInfo.listFile();          // 遍历设备rootinfos[0]的根目录,返回迭代器对象
94     // let fileIterator = rootInfo.scanFile(filter); // 过滤设备rootinfos[0]满足指定条件的文件信息,返回迭代对象
95     if (!fileIterator) {
96       console.error("listFile interface returns an undefined object");
97     }
98     while (!isDone) {
99       let result = fileIterator.next();
100       console.info("next result = " + JSON.stringify(result));
101       isDone = result.done;
102       if (!isDone)
103         fileInfos.push(result.value);
104     }
105   } catch (err) {
106    let error: BusinessError = err as BusinessError;
107     console.error("listFile failed, errCode:" + error.code + ", errMessage:" + error.message);
108   }
109
110   // 从指定的目录开始
111   let fileInfoDir: fileAccess.FileInfo = fileInfos[0]; // fileInfoDir 表示某个目录信息
112   let subFileInfos: Array<fileAccess.FileInfo> = [];
113   let isDone02: boolean = false;
114   let filter02: Filter = {suffix : [".txt", ".jpg", ".xlsx"]}; // 设定过滤条件
115   try {
116     let fileIterator = fileInfoDir.listFile(); // 遍历特定的目录fileinfo,返回迭代器对象
117     // let fileIterator = rootInfo.scanFile(filter02); // 过滤特定的目录fileinfo,返回迭代器对象
118     if (!fileIterator) {
119       console.error("listFile interface returns an undefined object");
120     }
121     while (!isDone02) {
122       let result = fileIterator.next();
123       console.info("next result = " + JSON.stringify(result));
124       isDone02 = result.done;
125       if (!isDone02)
126         subFileInfos.push(result.value);
127     }
128   } catch (err) {
129    let error: BusinessError = err as BusinessError;
130     console.error("listFile failed, errCode:" + error.code + ", errMessage:" + error.message);
131   }
132   ```
133
1345. 操作文件或目录。
135   开发者可以集成文件访问框架的接口,完成一些用户行为,比如删除文件(目录)、重命名文件(目录)、新建文件(目录)、移动文件(目录)等。以下示例展示了如何创建一个文件,其他接口请参见[API参考](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md)。
136
137   ```ts
138   import { BusinessError } from '@kit.BasicServicesKit';
139
140   // 以本地设备为例
141   // 创建文件
142   // 示例代码sourceUri是Download目录的fileinfo中的URI
143   // 开发者应根据自己实际获取fileinfo的URI进行开发
144   async function creatFile(): Promise<void> {
145     let sourceUri: string = "file://docs/storage/Users/currentUser/Download";
146     let displayName: string = "file1";
147     let fileUri: string = '';
148     try {
149       // fileAccessHelperAllServer 参考 fileAccess.createFileAccessHelper 示例代码获取
150       fileUri = await fileAccessHelperAllServer.createFile(sourceUri, displayName);
151       if (!fileUri) {
152         console.error("createFile return undefined object");
153       }
154       console.info("createFile sucess, fileUri: " + JSON.stringify(fileUri));
155     } catch (err) {
156      let error: BusinessError = err as BusinessError;
157      console.error("createFile failed, errCode:" + error.code + ", errMessage:" + error.message);
158     };
159   }
160   ```
161
162## 监听设备上下线
163
164开发设备上下线的相关API详细介绍请参见[API参考](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md)。
165
166notify接口不仅可以用来监听目录的变化,还能监听设备上线,下线功能。
167
168
1691. 权限配置和导入模块。
170
171   申请ohos.permission.FILE_ACCESS_MANAGERohos.permission.GET_BUNDLE_INFO_PRIVILEGED权限,配置方式请参见[访问控制授权申请](../security/AccessToken/declare-permissions.md)。
172
173   > **说明:**
174   >
175   > ohos.permission.FILE_ACCESS_MANAGER是使用文件访问框架接口的基础权限。
176   >
177   > ohos.permission.GET_BUNDLE_INFO_PRIVILEGED权限可以用于查询系统内当前支持的文件管理服务端应用信息。
178
1792. 导入依赖模块。
180
181   ```ts
182   import { fileAccess } from '@kit.CoreFileKit';
183   import { fileExtensionInfo } from '@kit.CoreFileKit';
184   ```
185
186 其中fileAccess提供了文件基础操作的API,fileExtensionInfo提供了应用开发的关键结构体。
187
1883. 提供监听回调方法。
189
190   ```ts
191   const callbackDir1 = (NotifyMessageDir: fileAccess.NotifyMessage) => {
192     if (NotifyMessageDir != undefined) {
193       console.log('NotifyType: ' + NotifyMessageDir.type + 'NotifyUri:' + NotifyMessageDir.uris[0]);
194     } else {
195      console.error("NotifyMessageDir is undefined");
196     }
197   }
198   ```
199
2004. 注册监听设备和取消设备监听。
201
202  开发者可以根据提供的[DEVICES_URI](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md#常量),传入方法registerObserver()中,就能监听设备上下线状态。传入方法unregisterObserver()中,就能取消设备上线,下线状态。
203
204   ```ts
205   import { BusinessError } from '@kit.BasicServicesKit';
206   import { common } from '@kit.AbilityKit';
207
208   //提供监听回调方法
209   const callbackDir1 = (NotifyMessageDir: fileAccess.NotifyMessage) => {
210     if (NotifyMessageDir != undefined) {
211       console.log('NotifyType: ' + NotifyMessageDir.type + 'NotifyUri:' + NotifyMessageDir.uris[0]);
212     } else {
213      console.error("NotifyMessageDir is undefined");
214     }
215   }
216
217   let context = getContext(this) as common.UIAbilityContext;
218   // 创建连接系统内所有文件管理服务端的helper对象
219   let fileAccessHelperAllServer: fileAccess.FileAccessHelper;
220   function createFileAccessHelper(): void {
221     try {    // this.context是EntryAbility传过来的Context
222       fileAccessHelperAllServer = fileAccess.createFileAccessHelper(context);
223       if (!fileAccessHelperAllServer) {
224         console.error("createFileAccessHelper interface returns an undefined object");
225       }
226     } catch (err) {
227         let error: BusinessError = err as BusinessError;
228         console.error("createFileAccessHelper failed, errCode:" + error.code + ", errMessage:" + error.message);
229     }
230   }
231   //注册监听设备,开发者可以根据提供的DEVICES_URI传入registerObserver()方法中,就能监听设备上线,下线状态。
232   async function UnregisterObserver03() {
233     try {
234       // 监听设备的上下线
235       fileAccessHelperAllServer.registerObserver(fileAccess.DEVICES_URI, true, callbackDir1);
236     } catch (err) {
237       let error: BusinessError = err as BusinessError;
238       console.error("unregisterObserver failed, errCode:" + error.code + ", errMessage:" + error.message);
239     }
240   }
241   //取消设备监听,开发者可以根据提供的DEVICES_URI传入unregisterObserver()方法中,就能取消设备上线,下线状态。
242   async function UnregisterObserver04() {
243     try {
244       // 取消监听设备的上下线
245       fileAccessHelperAllServer.unregisterObserver(fileAccess.DEVICES_URI, callbackDir1);
246     } catch (err) {
247       let error: BusinessError = err as BusinessError;
248       console.error("unregisterObserver failed, errCode:" + error.code + ", errMessage:" + error.message);
249     }
250   }
251   ```
252