1e41f4b71Sopenharmony_ci# Developing a File Manager Application (for System Applications Only)
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ciOpenHarmony is prebuilt with the **FileManager** application. You can also develop your own file manager application as required.
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci## How to Develop
6e41f4b71Sopenharmony_ciFor details about the APIs used to develop a file manager, see [User File Access and Management](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md).
7e41f4b71Sopenharmony_ci
8e41f4b71Sopenharmony_ci1. Apply for permissions required.<br>Apply for the ohos.permission.FILE_ACCESS_MANAGER and ohos.permission.GET_BUNDLE_INFO_PRIVILEGED permissions. For details, see [Requesting Permissions for System_basic Applications](../security/AccessToken/determine-application-mode.md#requesting-permissions-for-system_basic-applications).
9e41f4b71Sopenharmony_ci   
10e41f4b71Sopenharmony_ci> **NOTE**
11e41f4b71Sopenharmony_ci   >
12e41f4b71Sopenharmony_ci   > - The ohos.permission.FILE_ACCESS_MANAGER permission allows your application to use the user file access framework APIs.
13e41f4b71Sopenharmony_ci   >
14e41f4b71Sopenharmony_ci   > - The ohos.permission.GET_BUNDLE_INFO_PRIVILEGED permission allows your application to obtain information about file management server applications supported by the system.
15e41f4b71Sopenharmony_ci   
16e41f4b71Sopenharmony_ci2. Import dependent modules.
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ci   ```ts
19e41f4b71Sopenharmony_ci   import { fileAccess } from '@kit.CoreFileKit';
20e41f4b71Sopenharmony_ci   import { fileExtensionInfo } from '@kit.CoreFileKit';
21e41f4b71Sopenharmony_ci   ```
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci   The **fileAccess** module provides APIs for basic file operations, and the **fileExtensionInfo** module provides key structs for application development.
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ci3. Query device information.<br>
26e41f4b71Sopenharmony_ci   You can obtain attributes of the devices managed by one or all file management servers in the system. You can also filter devices as required.
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ci   In the user file access framework, **RootInfo** indicates the attribute information of a device. For example, obtain **RootInfo** of all devices.
29e41f4b71Sopenharmony_ci
30e41f4b71Sopenharmony_ci   ```ts
31e41f4b71Sopenharmony_ci   import { common } from '@kit.AbilityKit';
32e41f4b71Sopenharmony_ci   import { BusinessError } from '@kit.BasicServicesKit';
33e41f4b71Sopenharmony_ci   import { Filter } from '@kit.CoreFileKit';
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ci   // Obtain the application context.
36e41f4b71Sopenharmony_ci   let context = getContext(this) as common.UIAbilityContext;
37e41f4b71Sopenharmony_ci
38e41f4b71Sopenharmony_ci   // Create a helper object for connecting to all file management servers in the system.
39e41f4b71Sopenharmony_ci   let fileAccessHelperAllServer: fileAccess.FileAccessHelper;
40e41f4b71Sopenharmony_ci   function createFileAccessHelper(): void {
41e41f4b71Sopenharmony_ci     try {    // this.context is the context passed from EntryAbility.
42e41f4b71Sopenharmony_ci       fileAccessHelperAllServer = fileAccess.createFileAccessHelper(context);
43e41f4b71Sopenharmony_ci       if (!fileAccessHelperAllServer) {
44e41f4b71Sopenharmony_ci         console.error("createFileAccessHelper interface returns an undefined object");
45e41f4b71Sopenharmony_ci       }
46e41f4b71Sopenharmony_ci     } catch (err) {
47e41f4b71Sopenharmony_ci         let error: BusinessError = err as BusinessError;
48e41f4b71Sopenharmony_ci         console.error("createFileAccessHelper failed, errCode:" + error.code + ", errMessage:" + error.message);
49e41f4b71Sopenharmony_ci     }
50e41f4b71Sopenharmony_ci   }
51e41f4b71Sopenharmony_ci   let rootInfos: Array<fileAccess.RootInfo> = [];
52e41f4b71Sopenharmony_ci   async function getRoots(): Promise<void>{
53e41f4b71Sopenharmony_ci     let rootIterator: fileAccess.RootIterator;
54e41f4b71Sopenharmony_ci     let isDone: boolean = false;
55e41f4b71Sopenharmony_ci     try {
56e41f4b71Sopenharmony_ci       rootIterator = await fileAccessHelperAllServer.getRoots();
57e41f4b71Sopenharmony_ci       if (!rootIterator) {
58e41f4b71Sopenharmony_ci         console.error("getRoots interface returns an undefined object");
59e41f4b71Sopenharmony_ci         return;
60e41f4b71Sopenharmony_ci       }
61e41f4b71Sopenharmony_ci       while (!isDone) {
62e41f4b71Sopenharmony_ci         let result = rootIterator.next();
63e41f4b71Sopenharmony_ci         console.info("next result = " + JSON.stringify(result));
64e41f4b71Sopenharmony_ci         isDone = result.done;
65e41f4b71Sopenharmony_ci         if (!isDone)
66e41f4b71Sopenharmony_ci           rootInfos.push(result.value);
67e41f4b71Sopenharmony_ci       }
68e41f4b71Sopenharmony_ci     } catch (err) {
69e41f4b71Sopenharmony_ci       let error: BusinessError = err as BusinessError;
70e41f4b71Sopenharmony_ci       console.error("getRoots failed, errCode:" + error.code + ", errMessage:" + error.message);
71e41f4b71Sopenharmony_ci     }
72e41f4b71Sopenharmony_ci   }
73e41f4b71Sopenharmony_ci   ```
74e41f4b71Sopenharmony_ci
75e41f4b71Sopenharmony_ci4. View directories.<br>
76e41f4b71Sopenharmony_ci   In the user file access framework, **FileInfo** indicates basic information about a file or folder. You can use **listfile()** to obtain a **FileIterator** object that traverses all files (folders) of the next level or use **scanfile()** to obtain a **FileIterator** object that meets the specified conditions.
77e41f4b71Sopenharmony_ci
78e41f4b71Sopenharmony_ci   Currently, **listfile()** and **scanfile()** can be called by the **RootInfo** object to traverse the next-level files or filter the entire directory tree. In addition, **listfile()** and **scanfile()** can be called by the **FileInfo** object to traverse the next-level files or filter the specified directories.
79e41f4b71Sopenharmony_ci
80e41f4b71Sopenharmony_ci   ```ts
81e41f4b71Sopenharmony_ci   import { BusinessError } from '@kit.BasicServicesKit';
82e41f4b71Sopenharmony_ci   import { Filter } from '@kit.CoreFileKit';
83e41f4b71Sopenharmony_ci
84e41f4b71Sopenharmony_ci   // Start from the root directory.
85e41f4b71Sopenharmony_ci   let rootInfos = [];
86e41f4b71Sopenharmony_ci   // Obtain rootInfos by using getRoots().
87e41f4b71Sopenharmony_ci   let rootInfo: fileAccess.RootInfo = rootInfos[0];
88e41f4b71Sopenharmony_ci   let fileInfos: Array<fileAccess.FileInfo> = [];
89e41f4b71Sopenharmony_ci   let isDone: boolean = false;
90e41f4b71Sopenharmony_ci   let filter: Filter = {suffix : [".txt", ".jpg", ".xlsx"]}; // Set the filter.
91e41f4b71Sopenharmony_ci   try {  
92e41f4b71Sopenharmony_ci     let fileIterator = rootInfo.listFile();          // Traverse the root directory of rootinfos[0] and return a FileIterator object.
93e41f4b71Sopenharmony_ci     // let fileIterator = rootInfo.scanFile(filter); // Filter device rootinfos[0] files that meet the specified conditions and return a FileIterator object.
94e41f4b71Sopenharmony_ci     if (!fileIterator) {
95e41f4b71Sopenharmony_ci       console.error("listFile interface returns an undefined object");
96e41f4b71Sopenharmony_ci     }
97e41f4b71Sopenharmony_ci     while (!isDone) {
98e41f4b71Sopenharmony_ci       let result = fileIterator.next();
99e41f4b71Sopenharmony_ci       console.info("next result = " + JSON.stringify(result));
100e41f4b71Sopenharmony_ci       isDone = result.done;
101e41f4b71Sopenharmony_ci       if (!isDone)
102e41f4b71Sopenharmony_ci         fileInfos.push(result.value);
103e41f4b71Sopenharmony_ci     }
104e41f4b71Sopenharmony_ci   } catch (err) {
105e41f4b71Sopenharmony_ci    let error: BusinessError = err as BusinessError;
106e41f4b71Sopenharmony_ci     console.error("listFile failed, errCode:" + error.code + ", errMessage:" + error.message);
107e41f4b71Sopenharmony_ci   }
108e41f4b71Sopenharmony_ci   
109e41f4b71Sopenharmony_ci   // Start from the specified directory.
110e41f4b71Sopenharmony_ci   let fileInfoDir: fileAccess.FileInfo = fileInfos[0]; // fileInfoDir indicates the information about a directory.
111e41f4b71Sopenharmony_ci   let subFileInfos: Array<fileAccess.FileInfo> = [];
112e41f4b71Sopenharmony_ci   let isDone02: boolean = false;
113e41f4b71Sopenharmony_ci   let filter02: Filter = {suffix : [".txt", ".jpg", ".xlsx"]}; // Set the filter.
114e41f4b71Sopenharmony_ci   try {
115e41f4b71Sopenharmony_ci     let fileIterator = fileInfoDir.listFile(); // Traverse files in the specified directory and return a FileIterator object.
116e41f4b71Sopenharmony_ci     // let fileIterator = rootInfo.scanFile(filter02); // Filter the files in the specified directory and return a FileIterator object.
117e41f4b71Sopenharmony_ci     if (!fileIterator) {
118e41f4b71Sopenharmony_ci       console.error("listFile interface returns an undefined object");
119e41f4b71Sopenharmony_ci     }
120e41f4b71Sopenharmony_ci     while (!isDone02) {
121e41f4b71Sopenharmony_ci       let result = fileIterator.next();
122e41f4b71Sopenharmony_ci       console.info("next result = " + JSON.stringify(result));
123e41f4b71Sopenharmony_ci       isDone02 = result.done;
124e41f4b71Sopenharmony_ci       if (!isDone02)
125e41f4b71Sopenharmony_ci         subFileInfos.push(result.value);
126e41f4b71Sopenharmony_ci     }
127e41f4b71Sopenharmony_ci   } catch (err) {
128e41f4b71Sopenharmony_ci    let error: BusinessError = err as BusinessError;
129e41f4b71Sopenharmony_ci     console.error("listFile failed, errCode:" + error.code + ", errMessage:" + error.message);
130e41f4b71Sopenharmony_ci   }
131e41f4b71Sopenharmony_ci   ```
132e41f4b71Sopenharmony_ci
133e41f4b71Sopenharmony_ci5. Perform operations on files or folders.<br>
134e41f4b71Sopenharmony_ci   You can integrate APIs of the user file access framework to implement user behaviors, such as deleting, renaming, creating, and moving a file or folder. The following example shows how to create a file. For details about other APIs, see [User File Access and Management](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md).
135e41f4b71Sopenharmony_ci
136e41f4b71Sopenharmony_ci   ```ts
137e41f4b71Sopenharmony_ci   import { BusinessError } from '@kit.BasicServicesKit';
138e41f4b71Sopenharmony_ci
139e41f4b71Sopenharmony_ci   // The local device is used as an example.
140e41f4b71Sopenharmony_ci   // Create a file.
141e41f4b71Sopenharmony_ci   // sourceUri is the URI in fileinfo of the Download directory.
142e41f4b71Sopenharmony_ci   // You need to use the obtained URI for development.
143e41f4b71Sopenharmony_ci   async function creatFile(): Promise<void> {
144e41f4b71Sopenharmony_ci     let sourceUri: string = "file://docs/storage/Users/currentUser/Download";
145e41f4b71Sopenharmony_ci     let displayName: string = "file1";
146e41f4b71Sopenharmony_ci     let fileUri: string = '';
147e41f4b71Sopenharmony_ci     try {
148e41f4b71Sopenharmony_ci       // Obtain fileAccessHelperAllServer by referring to the sample code of fileAccess.createFileAccessHelper.
149e41f4b71Sopenharmony_ci       fileUri = await fileAccessHelperAllServer.createFile(sourceUri, displayName);
150e41f4b71Sopenharmony_ci       if (!fileUri) {
151e41f4b71Sopenharmony_ci         console.error("createFile return undefined object");
152e41f4b71Sopenharmony_ci       }
153e41f4b71Sopenharmony_ci       console.info("createFile sucess, fileUri: " + JSON.stringify(fileUri));
154e41f4b71Sopenharmony_ci     } catch (err) {
155e41f4b71Sopenharmony_ci      let error: BusinessError = err as BusinessError;
156e41f4b71Sopenharmony_ci      console.error("createFile failed, errCode:" + error.code + ", errMessage:" + error.message);
157e41f4b71Sopenharmony_ci     };
158e41f4b71Sopenharmony_ci   }
159e41f4b71Sopenharmony_ci   ```
160e41f4b71Sopenharmony_ci
161e41f4b71Sopenharmony_ci## Listening for Device Online/Offline Status
162e41f4b71Sopenharmony_ci
163e41f4b71Sopenharmony_ciFor details about the APIs, see [User File Access and Management](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md).
164e41f4b71Sopenharmony_ci
165e41f4b71Sopenharmony_ciThe **notify** interface can be used to observe not only the changes of directories, but also the device online/offline status.
166e41f4b71Sopenharmony_ci
167e41f4b71Sopenharmony_ci
168e41f4b71Sopenharmony_ci1. Apply for permissions required.<br>
169e41f4b71Sopenharmony_ci
170e41f4b71Sopenharmony_ci   Apply for the ohos.permission.FILE_ACCESS_MANAGER and ohos.permission.GET_BUNDLE_INFO_PRIVILEGED permissions. For details, see [Declaring Permissions](../security/AccessToken/declare-permissions.md).
171e41f4b71Sopenharmony_ci
172e41f4b71Sopenharmony_ci   > **NOTE**
173e41f4b71Sopenharmony_ci   >
174e41f4b71Sopenharmony_ci   > - The ohos.permission.FILE_ACCESS_MANAGER permission allows your application to use the user file access framework APIs.
175e41f4b71Sopenharmony_ci   >- The ohos.permission.GET_BUNDLE_INFO_PRIVILEGED permission allows your application to obtain information about file management server applications supported by the system.
176e41f4b71Sopenharmony_ci   
177e41f4b71Sopenharmony_ci2. Import dependent modules.
178e41f4b71Sopenharmony_ci
179e41f4b71Sopenharmony_ci   ```ts
180e41f4b71Sopenharmony_ci   import { fileAccess } from '@kit.CoreFileKit';
181e41f4b71Sopenharmony_ci   import { fileExtensionInfo } from '@kit.CoreFileKit';
182e41f4b71Sopenharmony_ci   ```
183e41f4b71Sopenharmony_ci   
184e41f4b71Sopenharmony_ci   The **fileAccess** module provides APIs for basic file operations, and the **fileExtensionInfo** module provides key structs for application development.
185e41f4b71Sopenharmony_ci   
186e41f4b71Sopenharmony_ci3. Define an observer callback.
187e41f4b71Sopenharmony_ci
188e41f4b71Sopenharmony_ci   ```ts
189e41f4b71Sopenharmony_ci   const callbackDir1 = (NotifyMessageDir: fileAccess.NotifyMessage) => {
190e41f4b71Sopenharmony_ci     if (NotifyMessageDir != undefined) {
191e41f4b71Sopenharmony_ci       console.log('NotifyType: ' + NotifyMessageDir.type + 'NotifyUri:' + NotifyMessageDir.uri[0]);
192e41f4b71Sopenharmony_ci     } else {
193e41f4b71Sopenharmony_ci      console.error("NotifyMessageDir is undefined");
194e41f4b71Sopenharmony_ci     }
195e41f4b71Sopenharmony_ci   }
196e41f4b71Sopenharmony_ci   ```
197e41f4b71Sopenharmony_ci
198e41f4b71Sopenharmony_ci4. Subscribe to the device online/offline status.
199e41f4b71Sopenharmony_ci
200e41f4b71Sopenharmony_ci     Pass in the constant [DEVICES_URI](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md#constant) to the **registerObserver** method to listen for the device online/offline status.
201e41f4b71Sopenharmony_ci
202e41f4b71Sopenharmony_ci      ```ts
203e41f4b71Sopenharmony_ci      import { BusinessError } from '@kit.BasicServicesKit';
204e41f4b71Sopenharmony_ci      async function UnregisterObserver03() {
205e41f4b71Sopenharmony_ci        try {
206e41f4b71Sopenharmony_ci          // Listen for the device online/offline status.
207e41f4b71Sopenharmony_ci          fileAccessHelper.registerObserver(fileAccess.DEVICES_URI, true, callbackDir1);
208e41f4b71Sopenharmony_ci        } catch (err) {
209e41f4b71Sopenharmony_ci          let error: BusinessError = err as BusinessError;
210e41f4b71Sopenharmony_ci          console.error("unregisterObserver failed, errCode:" + error.code + ", errMessage:" + error.message);
211e41f4b71Sopenharmony_ci        }
212e41f4b71Sopenharmony_ci      }
213e41f4b71Sopenharmony_ci      ```
214e41f4b71Sopenharmony_ci
215e41f4b71Sopenharmony_ci5. Unsubscribe from the device online/offline status.
216e41f4b71Sopenharmony_ci
217e41f4b71Sopenharmony_ci   Pass in the constant [DEVICES_URI](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md#constant) to the **unregisterObserver** method to unsubscribe from the device online/offline status.
218e41f4b71Sopenharmony_ci
219e41f4b71Sopenharmony_ci      ```ts
220e41f4b71Sopenharmony_ci      import { BusinessError } from '@kit.BasicServicesKit';
221e41f4b71Sopenharmony_ci        try {
222e41f4b71Sopenharmony_ci          // Unsubscribe from the device online/offline status.
223e41f4b71Sopenharmony_ci          fileAccessHelper.unregisterObserver(fileAccess.DEVICES_URI, callbackDir1);
224e41f4b71Sopenharmony_ci        } catch (err) {
225e41f4b71Sopenharmony_ci          let error: BusinessError = err as BusinessError;
226e41f4b71Sopenharmony_ci          console.error("unregisterObserver failed, errCode:" + error.code + ", errMessage:" + error.message);
227e41f4b71Sopenharmony_ci        }
228e41f4b71Sopenharmony_ci      ```