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

int: Operation Result Codes

Directory browsing

listFiles

Folder: Folder
int: Starting offset
boolean: Whether notify result

int: Operation Result Codes

Directory browsing

loadMore

SDCardBean: SDCardBean

int: Operation Result Codes

Load more file information

appenBrowse

FileStruct: FileStruct
SDCardBean: SDCardBean

int: Operation Result Codes

Browse next level directory

appenBrowse

Folder: Folder

int: Operation Result Codes

Browse next level directory

backBrowse

SDCardBean: SDCardBean

int: Operation Result Codes

Return to previous directory (with callback)

backBrowse

SDCardBean: SDCardBean
boolean: Whether callback file data

int: Operation Result Codes

Return to previous directory

deleteFile

SDCardBean: SDCardBean
List<FileStruct>: Delete file list
DeleteCallback: Delete file callback

int: Operation Result Codes

Delete file

deleteFile

SDCardBean: SDCardBean
List<FileStruct>: Delete file list
boolean: Whether need prepare environment
DeleteCallback: Delete file callback

int: Operation Result Codes

Delete file

deleteFile

List<FileStruct>: Delete file list
boolean: Whether need prepare environment
DeleteCallback: Delete file callback

int: Operation Result Codes

Delete file

playFile

FileStruct: FileStruct
SDCardBean: SDCardBean

int: Operation Result Codes

Play music file

playFile

RegFile: RegFile

int: Operation Result Codes

Play music file

formatDevice

SDCardBean: SDCardBean
OperatCallback: Operation callback

int: Operation Result Codes

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

  1. Confirm with firmware whether backup or preparation environment needed for formatting

  2. 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

  1. 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

  1. 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

  2. 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

  1. Need to check whether storage device is online before using file management related interfaces

  2. Special operations need to confirm with firmware whether supported

  3. File operations not allowed during OTA