1. File Management
Manage files on device sd, usb, flash, enabling file browsing, deletion, downloading, reading, formatting, etc. Typical function: Music management
1.1. File Browsing
Function Name |
Parameters |
Return Value |
Description |
|---|---|---|---|
addFileObserver |
FileObserver: FileObserver |
void |
Register directory browsing observer |
removeFileObserver |
FileObserver: FileObserver |
void |
Unregister directory browsing observer |
setPageSize |
int: Number of files per browse, range: [1, 30] |
void |
Set number of files per browse |
getPageSize |
void |
int: Number of files per browse |
Get number of files per browse |
getOnlineStorage |
FileStruct: FileStruct |
SDCardBean: SDCardBean |
Get online storage |
getCurrentReadFile |
SDCardBean: SDCardBean |
Folder: Folder |
Get current browsing directory |
getCurrentFileStructs |
SDCardBean: SDCardBean |
List<FileStruct>: Child file list |
Read loaded files in current directory |
isReading |
void |
boolean: Whether reading files |
Whether reading files |
isOnline |
int: Storage index |
boolean: Whether online |
Whether storage is online |
getSdCardBeans |
void |
List<SDCardBean>: Storage list |
Get storage information list |
getOnlineDev |
void |
List<SDCardBean>: Online storage list |
Get online storage list |
listFiles |
Folder: Folder
int: Starting offset
|
Directory browsing |
|
listFiles |
Directory browsing |
||
loadMore |
SDCardBean: SDCardBean |
Load more file information |
|
appenBrowse |
FileStruct: FileStruct
SDCardBean: SDCardBean
|
Browse next level directory |
|
appenBrowse |
Folder: Folder |
Browse next level directory |
|
backBrowse |
SDCardBean: SDCardBean |
Return to previous directory (with callback) |
|
backBrowse |
SDCardBean: SDCardBean
boolean: Whether callback file data
|
Return to previous directory |
|
deleteFile |
Delete file |
||
deleteFile |
SDCardBean: SDCardBean
List<FileStruct>: Delete file list
boolean: Whether need prepare environment
DeleteCallback: Delete file callback
|
Delete file |
|
deleteFile |
List<FileStruct>: Delete file list
boolean: Whether need prepare environment
DeleteCallback: Delete file callback
|
Delete file |
|
playFile |
FileStruct: FileStruct
SDCardBean: SDCardBean
|
Play music file |
|
playFile |
RegFile: RegFile |
Play music file |
|
formatDevice |
SDCardBean: SDCardBean
OperatCallback: Operation callback
|
Format storage |
|
cleanCache |
void |
void |
Clear all cache |
cleanCache |
BluetoothDevice: Bluetooth device |
void |
Clear all cache for specified device |
cleanCache |
SDCardBean: SDCardBean |
void |
Clear all cache for specified storage |
1.1.1. Operation Result Codes
Name |
Value |
Description |
|---|---|---|
FileBrowseConstant#SUCCESS |
0(0x0000) |
Success result |
FileBrowseConstant#ERR_PARAM |
4096(0x1001) |
Invalid parameter |
FileBrowseConstant#ERR_BUSY |
12291(0x3003) |
System busy |
FileBrowseConstant#ERR_READING |
16385(0x4001) |
Reading directory |
FileBrowseConstant#ERR_OFFLINE |
16384(0x4000) |
Storage offline |
FileBrowseConstant#ERR_LOAD_FINISHED |
16386(0x4002) |
File list loading finished |
FileBrowseConstant#ERR_NO_DATA |
16387(0x4003) |
Missing file data |
FileBrowseConstant#ERR_BEYOND_MAX_DEPTH |
16388(0x4004) |
Exceeded limit directory level |
FileBrowseConstant#ERR_OPERATION_TIMEOUT |
4098(0x1003) |
Operation timeout |
FileBrowseConstant#ERR_FILE_NOT_IN_STORAGE |
16390(0x4006) |
File structure inconsistent with storage
Indicates input parameter conflict
|
1.1.2. FileObserver
Directory browsing observer
public interface FileObserver {
/**
* Callback after receiving directory file data
*
* @param fileStructs File structure list
*/
void onFileReceiver(List<FileStruct> fileStructs);
/**
* One file read ends
*
* @param isEnd Whether ended
*/
void onFileReadStop(boolean isEnd);
/**
* File read starts
*/
void onFileReadStart();
/**
* File read fails
*
* @param reason Error code
*/
void onFileReadFailed(int reason);
/**
* Device storage status change
*
* @param onLineCards Online device list
*/
void onSdCardStatusChange(List<SDCardBean> onLineCards);
/**
* File on-demand success callback
*/
void OnFlayCallback(boolean success);
}
1.1.3. FileStruct
File structure
public class FileStruct implements IDataOp, Parcelable {
/**
* Whether file
*
* <p>Result explanation:
* true -- File
* false -- Folder</p>
*/
private boolean file;
/**
* Whether Unicode encoded
*
* <p>
* Result explanation:
* true -- Unicode encoding
* false -- ASCII encoding
* </p>
*/
private boolean unicode;
/**
* Cluster number. Unique identifier
*/
private int cluster = 0;
/**
* Folder number
*/
private short fileNum = 1;
/**
* File name
*/
private String name = "";
/**
* Storage type
*/
private byte devIndex;
}
1.1.4. SDCardBean
Storage information
public class SDCardBean implements Parcelable {
/**
* SD card type
*/
public static final int SD = 0;
/**
* USB type
*/
public static final int USB = 1;
/**
* Flash type
*/
public static final int FLASH = 2;
/**
* LineIn type
*/
public static final int LINEIN = 3;
/**
* Flash2 type
*/
public static final int FLASH_2 = 4;
//index
/**
* USB index
*/
public static final int INDEX_USB = 0;
/**
* SD0 index
*/
public static final int INDEX_SD0 = 1;
/**
* SD1 type
*/
public static final int INDEX_SD1 = 2;
/**
* Flash index
*/
public static final int INDEX_FLASH = 3;
/**
* Input device index
*/
public static final int INDEX_LINE_IN = 4;
/**
* Flash2 index
*/
public static final int INDEX_FLASH2 = 5;
/**
* Flash3 index
*/
public static final int INDEX_FLASH3 = 6;
/**
* Storage index
*/
private int index;
/**
* Storage type
*/
private int type;
/**
* Storage name
*/
private String name;
/**
* Storage handler
*/
private int devHandler = -1;
/**
* Whether online
*/
private boolean online;
/**
* Operation device
*/
private BluetoothDevice device;
}
1.1.5. Folder
Folder
public class Folder extends File {
/**
* File list
*/
private final transient List<File> files = new ArrayList<>();
/**
* Whether load finished
*/
private boolean isLoadFinish = false;
}
1.1.6. RegFile
Resource file
public class RegFile extends File {
}
public abstract class File extends FileStruct {
/**
* Parent folder
*/
private transient final Folder parent;
/**
* Directory level
*/
private final int level;
}
1.2. Directory Browsing
FileObserver fileObserver = new FileObserver() {
@Override
public void onFileReceiver(List<FileStruct> fileStructs) {
// Read file list, only callback current read file list
}
@Override
public void onFileReadStop(boolean isEnd) {
// File list read ends
}
@Override
public void onFileReadStart() {
// Start file list read
}
@Override
public void onFileReadFailed(int reason) {
// File list read fails
}
@Override
public void onSdCardStatusChange(List<SDCardBean> onLineCards) {
//Online device changes
}
@Override
public void OnFlayCallback(boolean success) {
//Song on-demand callback
}
};
//Step 1: Register observer
// Step 2: Get online device list, can handle device status changes via fileObserver
FileBrowseManager.getInstance().addFileObserver(fileObserver);
// Step 3: Read current directory being read by current device
List<SDCardBean> list = FileBrowseManager.getInstance().getOnlineDev();
if(list.size()<1){
//No online devices
return;
}
SDCardBean sdCardBean = list.get(0);//Get device, if multiple devices, get appropriate device based on requirements
Folder currentFolder = FileBrowseManager.getInstance().getCurrentReadFile(sdCardBean);
//Step 4: Get child files already read in cache under current directory
List<FileStruct> fileStructs = currentFolder.getChildFileStructs();
//Step 5: Browsing operations
//Load more
FileBrowseManager.getInstance().loadMore(sdCardBean);
//Enter next level directory
FileStruct fileStruct = currentFolder.getChildFileStructs().get(0);//Get required folder based on needs
FileBrowseManager.getInstance().appenBrowse(fileStruct, sdCardBean);
//Return to previous directory without list callback
boolean hasEvent = true;//Whether need FileObserver event callback
FileBrowseManager.getInstance().backBrowse(sdCardBean,hasEvent);
//On-demand file
FileBrowseManager.getInstance().playFile(fileStruct, sdCardBean);
1.3. File Deletion
List<SDCardBean> list = FileBrowseManager.getInstance().getOnlineDev();
if(list.size() < 1){
//No online devices
return;
}
SDCardBean sdCardBean = list.get(0);//Get device, if multiple devices, get appropriate device based on requirements
List<FileStruct> fileStructs = new ArrayList<>();//Note fileStructs must be in sdCardBean
boolean withEnv = false;//Prepare environment, generally use false
FileBrowseManager.getInstance().deleteFile(sdCardBean, fileStructs,withEnv, new DeleteCallback() {
@Override
public void onSuccess(FileStruct fileStruct) {
//Success
}
@Override
public void onError(int code, FileStruct fileStruct) {
//fileStruct deletion failed
}
@Override
public void onFinish() {
//Deletion ends, check for failed deletions via onError
}
});
1.4. Formatting
//Formatting, only format device
List<SDCardBean> list = FileBrowseManager.getInstance().getOnlineDev();
if (list.size() < 1) {
//No online devices
return;
}
SDCardBean sdCardBean = list.get(0);//Get device, if multiple devices, get appropriate device based on requirements
FileBrowseManager.getInstance().formatDevice(sdCardBean, new OperatCallback() {
@Override
public void onSuccess() {
//Success
}
@Override
public void onError(int code) {
//Failure
}
});
Important
Confirm with firmware whether backup or preparation environment needed for formatting
Confirm with firmware whether backup or preparation environment needed for file deletion
1.5. Large File Transfer
1.5.1. File Download (APP -> Device)
Corresponding Class |
Function Description |
|---|---|
TransferTask |
Large file transfer task (Path method) |
UriTransferTask |
Large file transfer task (Uri method) |
Sample Code
//WatchManager is a subclass of WatchOpImpl, must configure sdk in 1.3
WatchManager watchManager = WatchManager.getInstance();
SDCardBean sdCardBean = DeviceChoseUtil.getTargetDev();//Get target device, need to check if device is null
if(sdCardBean == null) return;
TransferTask.Param param = new TransferTask.Param();
param.devHandler = sdCardBean.getDevHandler();//Set device handler, can understand as selecting file storage device: sd, usb, etc.,
/**
* Whether to use other encoding method.
* Default false, encoding methods are:<br/>
* - Short file name: GBK {@link Charset#forName(String)}<br/>
* - Long file name: Add "\\U" + Unicode encoded data + terminator, {@link Charset#forName(String)}
* If true, then {@link #encodeType} attribute takes effect
*/
param.isOtherEncode = false;
String path = "File path to transfer";
ITask task = new TransferTask(watchManager,path,param);
task.setListener(new TaskListener() {
@Override
public void onBegin() {
//File transfer starts
}
@Override
public void onProgress(int progress) {
//Progress callback
}
@Override
public void onFinish() {
//Transfer ends
}
@Override
public void onError(int code, String msg) {
//Transfer exception
}
@Override
public void onCancel(int reason) {
//Transfer cancelled
}
});
//Start file transfer
if(!task.isRun()){
task.start();
}else {
//File transferring
}
// Cancel transfer actively
task.cancel((byte) 0x01);
Important
Need to ensure file has access permission, on Android API 28+, some files cannot be read via file path, can use UriTransferTask instead of TransferTask, both only differ in constructor
ITask task = null; if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { task = new UriTransferTask(context, watchManager, uri, title, param); } else { task = new TransferTask(watchManager, path, param); }
1.5.1.1. TransferTask.Param
public static class Param {
public int devHandler; //Device handler
public boolean appHasCrc16 = true; //Whether app supports crc16, generally use default value
public boolean useFlash = false; //Whether flash device
/**
* Whether to use other encoding method
*
* <p>
* Default false, encoding methods are:<br/>
* - Short file name: GBK {@link Charset#forName(String)}<br/>
* - Long file name: Add "\\U" + Unicode encoded data + terminator, {@link Charset#forName(String)}
* If true, then {@link #encodeType} attribute takes effect
* </p>
*/
public boolean isOtherEncode = false; //Whether to use other encoding method
/**
* Encoding method
*
* <strong>1. Note requires {@link #isOtherEncode} to be true for field to take effect</strong>
*/
public String encodeType = StandardCharsets.UTF_16LE.name(); //Default encoding method
/**
* Specify output directory path
* If empty, specify output file path.
*/
public String outputDirPath;
}
1.5.2. File Reading (Device -> APP)
Corresponding Class |
Function Description |
|---|---|
GetFileByClusterTask |
Read file by file cluster number task |
GetFileByNameTask |
Read file by file name task |
1.5.2.1. Read File by File Cluster Number
Recommended file reading method
Sample Code
//WatchManager is a subclass of WatchOpImpl, must configure sdk in 1.3
WatchManager watchManager = WatchManager.getInstance();
List<SDCardBean> list = FileBrowseManager.getInstance().getOnlineDev();
if (list.size() < 1) {
//No online devices
return;
}
SDCardBean sdCardBean = list.get(0);//Get device, if multiple devices, get appropriate device based on requirements
FileStruct fileStruct = null;//Note fileStructs must be in sdCardBean
int devHandle = sdCardBean.getDevHandler();
int cluster = fileStruct.getCluster();
int offset = 0;
String path = "Save path for read content";
GetFileByClusterTask.Param param = new GetFileByClusterTask.Param(devHandle, 0, cluster, path);
GetFileByClusterTask task = new GetFileByClusterTask(watchManager, param);
task.setListener(new TaskListener() {
@Override
public void onBegin() {
//Start
}
@Override
public void onProgress(int progress) {
//Progress callback
}
@Override
public void onFinish() {
//Success
}
@Override
public void onError(int code, String msg) {
//Failure
}
@Override
public void onCancel(int reason) {
//Cancel
}
});
task.start();
1.5.2.2. Read File by File Name
Not recommended, requires firmware support
//WatchManager is a subclass of WatchOpImpl, must configure sdk in 1.3
WatchManager watchManager = WatchManager.getInstance();
String name = "File name";
String path = "Save path";
List<SDCardBean> list = FileBrowseManager.getInstance().getOnlineDev();
if (list.size() < 1) {
//No online devices
return;
}
SDCardBean sdCardBean = list.get(0);//Get device, if multiple devices, get appropriate device based on requirements
int devHandle = sdCardBean.getDevHandler();
boolean unicode = false;//Whether filename supports long filenames (long filenames use unicode encoding, short filenames use 8+3 structure ASCII encoding)
GetFileByNameTask.Param param = new GetFileByNameTask.Param(devHandle,name,path,unicode);
GetFileByNameTask task = new GetFileByNameTask(watchManager,param);
task.setListener(new TaskListener() {
@Override
public void onBegin() {
//Start
}
@Override
public void onProgress(int progress) {
//Progress callback
}
@Override
public void onFinish() {
//Success
}
@Override
public void onError(int code, String msg) {
//Failure
}
@Override
public void onCancel(int reason) {
//Cancel
}
});
task.start();
Important
Same watchManager instance can only run one file management operation at a time, if need to execute multiple operations continuously, need to do serial restriction
File operations not allowed during OTA
1.6. Special Operations (Requires device configuration)
When using following interfaces, please communicate with firmware developers whether supported.
1.6.1. Delete File by Name
//WatchManager is a subclass of WatchOpImpl, must configure sdk in 1.3
WatchManager watchManager = WatchManager.getInstance();
String name = "File name";
DeleteFileByNameCmd deleteFileByNameCmd = new DeleteFileByNameCmd(new DeleteFileByNameCmd.Param(name));
watchManager.sendRcspCommand(watchManager.getTargetDevice(), deleteFileByNameCmd, new BooleanRcspActionCallback("DeleteFileByName",
new OnOperationCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
//Success
}
@Override
public void onFailed(BaseError error) {
//Failure
}
}));
Important
Need to check whether storage device is online before using file management related interfaces
Special operations need to confirm with firmware whether supported
File operations not allowed during OTA