1. 文件管理
管理设备sd、usb、flash的文件, 可以实现文件的浏览、删除, 文件下载、文件读取、格式化等功能。典型功能: 音乐管理
1.1. 文件浏览
函数名 |
参数 |
返回值 |
作用说明 |
|---|---|---|---|
addFileObserver |
FileObserver: FileObserver |
void |
注册目录浏览观察者 |
removeFileObserver |
FileObserver: FileObserver |
void |
注销目录浏览观察者 |
setPageSize |
int: 每次浏览文件个数,范围:[1, 30] |
void |
设置每次浏览文件个数 |
getPageSize |
void |
int: 每次浏览文件个数 |
获取每次浏览文件个数 |
getOnlineStorage |
FileStruct: FileStruct |
SDCardBean: SDCardBean |
获取在线存储器 |
getCurrentReadFile |
SDCardBean: SDCardBean |
Folder: Folder |
获取当前浏览目录 |
getCurrentFileStructs |
SDCardBean: SDCardBean |
List<FileStruct>: 子文件列表 |
读取当前目录下的已加载文件 |
isReading |
void |
boolean: 是否正在读取文件 |
是否正在读取文件 |
isOnline |
int: 存储器索引号 |
boolean: 是否在线 |
存储器是否在线 |
getSdCardBeans |
void |
List<SDCardBean>: 存储器列表 |
获取存储器信息列表 |
getOnlineDev |
void |
List<SDCardBean>: 在线存储器列表 |
获取在线存储器列表 |
listFiles |
Folder: Folder
int: 起始偏移
|
int: 操作结果码 |
目录浏览 |
listFiles |
int: 操作结果码 |
目录浏览 |
|
loadMore |
SDCardBean: SDCardBean |
int: 操作结果码 |
加载更多文件信息 |
appenBrowse |
FileStruct: FileStruct
SDCardBean: SDCardBean
|
int: 操作结果码 |
浏览下一级目录 |
appenBrowse |
Folder: Folder |
int: 操作结果码 |
浏览下一级目录 |
backBrowse |
SDCardBean: SDCardBean |
int: 操作结果码 |
返回上一级目录(有回调) |
backBrowse |
SDCardBean: SDCardBean
boolean: 是否回调文件数据
|
int: 操作结果码 |
返回上一级目录 |
deleteFile |
int: 操作结果码 |
删除文件 |
|
deleteFile |
int: 操作结果码 |
删除文件 |
|
deleteFile |
List<FileStruct>: 删除文件列表
boolean: 是否需要准备环境
DeleteCallback: 删除文件回调
|
int: 操作结果码 |
删除文件 |
playFile |
FileStruct: FileStruct
SDCardBean: SDCardBean
|
int: 操作结果码 |
播放音乐文件 |
playFile |
RegFile: RegFile |
int: 操作结果码 |
播放音乐文件 |
formatDevice |
SDCardBean: SDCardBean
OperatCallback: 操作回调
|
int: 操作结果码 |
格式化存储器 |
cleanCache |
void |
void |
清除所有缓存 |
cleanCache |
BluetoothDevice: 蓝牙设备 |
void |
清除指定设备的所有缓存 |
cleanCache |
SDCardBean: SDCardBean |
void |
清除指定存储器的所有缓存 |
1.1.1. 操作结果码
名称 |
码值 |
描述 |
|---|---|---|
FileBrowseConstant#SUCCESS |
0(0x0000) |
成功结果 |
FileBrowseConstant#ERR_PARAM |
4096(0x1001) |
无效参数 |
FileBrowseConstant#ERR_BUSY |
12291(0x3003) |
系统繁忙 |
FileBrowseConstant#ERR_READING |
16385(0x4001) |
正在目录浏览 |
FileBrowseConstant#ERR_OFFLINE |
16384(0x4000) |
存储器下线 |
FileBrowseConstant#ERR_LOAD_FINISHED |
16386(0x4002) |
文件列表已加载完毕 |
FileBrowseConstant#ERR_NO_DATA |
16387(0x4003) |
丢失文件数据 |
FileBrowseConstant#ERR_BEYOND_MAX_DEPTH |
16388(0x4004) |
超过限制目录层级 |
FileBrowseConstant#ERR_OPERATION_TIMEOUT |
4098(0x1003) |
操作超时 |
FileBrowseConstant#ERR_FILE_NOT_IN_STORAGE |
16390(0x4006) |
文件结构与存储器不一致
说明输入参数冲突
|
1.1.2. FileObserver
目录浏览观察者
public interface FileObserver {
/**
* 收到目录文件数据后回调
*
* @param fileStructs 文件结构列表
*/
void onFileReceiver(List<FileStruct> fileStructs);
/**
* 一次文件读取结束
*
* @param isEnd 是否结束
*/
void onFileReadStop(boolean isEnd);
/**
* 文件读取开始
*/
void onFileReadStart();
/**
* 文件读取失败
*
* @param reason 错误码
*/
void onFileReadFailed(int reason);
/**
* 设备的存储设备状态变化
*
* @param onLineCards 在线设备列表
*/
void onSdCardStatusChange(List<SDCardBean> onLineCards);
/**
* 文件点播成功回调
*/
void OnFlayCallback(boolean success);
}
1.1.3. FileStruct
文件结构
public class FileStruct implements IDataOp, Parcelable {
/**
* 是否文件
*
* <p>结果说明:
* true -- 文件
* false -- 文件夹</p>
*/
private boolean file;
/**
* 是否Unicode编码
*
* <p>
* 结果说明:
* true -- Unicode编码
* false -- ASCII编码
* </p>
*/
private boolean unicode;
/**
* 簇号。唯一标识
*/
private int cluster = 0;
/**
* 文件夹序号
*/
private short fileNum = 1;
/**
* 文件名
*/
private String name = "";
/**
* 存储器类型
*/
private byte devIndex;
}
1.1.4. SDCardBean
存储器信息
public class SDCardBean implements Parcelable {
/**
* SD卡类型
*/
public static final int SD = 0;
/**
* USB类型
*/
public static final int USB = 1;
/**
* Flash类型
*/
public static final int FLASH = 2;
/**
* LineIn类型
*/
public static final int LINEIN = 3;
/**
* Flash2类型
*/
public static final int FLASH_2 = 4;
//index
/**
* USB索引
*/
public static final int INDEX_USB = 0;
/**
* SD0索引
*/
public static final int INDEX_SD0 = 1;
/**
* SD1类型
*/
public static final int INDEX_SD1 = 2;
/**
* Flash索引
*/
public static final int INDEX_FLASH = 3;
/**
* 输入设备索引
*/
public static final int INDEX_LINE_IN = 4;
/**
* Flash2索引
*/
public static final int INDEX_FLASH2 = 5;
/**
* Flash3索引
*/
public static final int INDEX_FLASH3 = 6;
/**
* 存储器索引
*/
private int index;
/**
* 存储器类型
*/
private int type;
/**
* 存储器名称
*/
private String name;
/**
* 存储器句柄
*/
private int devHandler = -1;
/**
* 是否在线
*/
private boolean online;
/**
* 操作设备
*/
private BluetoothDevice device;
}
1.1.5. Folder
文件夹
public class Folder extends File {
/**
* 文件列表
*/
private final transient List<File> files = new ArrayList<>();
/**
* 是否加载完成
*/
private boolean isLoadFinish = false;
}
1.1.6. RegFile
资源文件
public class RegFile extends File {
}
public abstract class File extends FileStruct {
/**
* 父类文件夹
*/
private transient final Folder parent;
/**
* 目录层级
*/
private final int level;
}
1.2. 目录浏览
FileObserver fileObserver = new FileObserver() {
@Override
public void onFileReceiver(List<FileStruct> fileStructs) {
// 读取到文件列表,仅仅回调本次读取的文件列表
}
@Override
public void onFileReadStop(boolean isEnd) {
// 文件列表读取结束
}
@Override
public void onFileReadStart() {
// 开始文件列表读取
}
@Override
public void onFileReadFailed(int reason) {
// 文件列表读取失败
}
@Override
public void onSdCardStatusChange(List<SDCardBean> onLineCards) {
//在线设备有变化
}
@Override
public void OnFlayCallback(boolean success) {
//歌曲点播回调
}
};
//第一步:注册观察者
// 第2步:获取在线设备列表,可以通过fileObserver处理设备状态变化
FileBrowseManager.getInstance().addFileObserver(fileObserver);
// 第3步:读取当前设备正在读的当前目录
List<SDCardBean> list = FileBrowseManager.getInstance().getOnlineDev();
if(list.size()<1){
//没有在线设备
return;
}
SDCardBean sdCardBean = list.get(0);//获取设备,如果有多个设备,请根据需求获取相应的设备
Folder currentFolder = FileBrowseManager.getInstance().getCurrentReadFile(sdCardBean);
//第4步:获取当前目录下已经读了但在缓存中的子文件
List<FileStruct> fileStructs = currentFolder.getChildFileStructs();
//第5步:浏览操作
//加载更多
FileBrowseManager.getInstance().loadMore(sdCardBean);
//进入下一级目录
FileStruct fileStruct = currentFolder.getChildFileStructs().get(0);//根据需要获取需要读取的文件夹
FileBrowseManager.getInstance().appenBrowse(fileStruct, sdCardBean);
//返回上一级目录没有列表回调
boolean hasEvent = true;//是否需要FileObserver的事件回调
FileBrowseManager.getInstance().backBrowse(sdCardBean,hasEvent);
//点播文件
FileBrowseManager.getInstance().playFile(fileStruct, sdCardBean);
1.3. 文件删除
List<SDCardBean> list = FileBrowseManager.getInstance().getOnlineDev();
if(list.size() < 1){
//没有在线设备
return;
}
SDCardBean sdCardBean = list.get(0);//获取设备,如果有多个设备,请根据需求获取相应的设备
List<FileStruct> fileStructs = new ArrayList<>();//注意fileStructs一定要是在sdCardBean中
boolean withEnv = false;//准备环境,一般使用false
FileBrowseManager.getInstance().deleteFile(sdCardBean, fileStructs,withEnv, new DeleteCallback() {
@Override
public void onSuccess(FileStruct fileStruct) {
//成功
}
@Override
public void onError(int code, FileStruct fileStruct) {
//fileStruct 删除失败
}
@Override
public void onFinish() {
//删除结束,通过onError判断是否有删除失败的文件
}
});
1.4. 格式化
//格式化,仅仅格式化设备
List<SDCardBean> list = FileBrowseManager.getInstance().getOnlineDev();
if (list.size() < 1) {
//没有在线设备
return;
}
SDCardBean sdCardBean = list.get(0);//获取设备,如果有多个设备,请根据需求获取相应的设备
FileBrowseManager.getInstance().formatDevice(sdCardBean, new OperatCallback() {
@Override
public void onSuccess() {
//成功
}
@Override
public void onError(int code) {
//失败
}
});
Important
格式化操作请和固件确认是否需要备份或者准备环境
删除文件操作请和固件确认是否需要备份或者准备环境
1.5. 大文件传输
1.5.1. 文件下载(APP -> 设备)
对应类 |
功能说明 |
|---|---|
TransferTask |
大文件传输任务(Path方式) |
UriTransferTask |
大文件传输任务(Uri方式) |
示例代码
//WatchManager是WatchOpImpl的子类,须在1.3配置好sdk
WatchManager watchManager = WatchManager.getInstance();
SDCardBean sdCardBean = DeviceChoseUtil.getTargetDev();//获取设备目标设备,这里需要判断设备是否为空
if(sdCardBean == null) return;
TransferTask.Param param = new TransferTask.Param();
param.devHandler = sdCardBean.getDevHandler();//设置设备句柄,可以理解为选择文件存储的设备:如sd,usb等,
/**
* 是否使用其他编码方式。
* 默认false,编码方式如下:<br/>
* - 短文件名: GBK {@link Charset#forName(String)}<br/>
* - 长文件名: 增加"\\U" + Unicode编码数据 + 结束符, {@link Charset#forName(String)}
* 若为true, 则{@link #encodeType} 属性生效
*/
param.isOtherEncode = false;
String path = "需要传输的文件路径";
ITask task = new TransferTask(watchManager,path,param);
task.setListener(new TaskListener() {
@Override
public void onBegin() {
//文件传输开始
}
@Override
public void onProgress(int progress) {
//进度回调
}
@Override
public void onFinish() {
//传输结束
}
@Override
public void onError(int code, String msg) {
//传输异常
}
@Override
public void onCancel(int reason) {
//传输已取消
}
});
//开始传输文件
if(!task.isRun()){
task.start();
}else {
//文件正在传输
}
// 主动取消传输
task.cancel((byte) 0x01);
Important
需要保证文件具有访问权限, 在Android API 28及以上, 部分文件无法通过文件路径读取, 可以使用UriTransferTask替代TransferTask, 两者在使用上仅仅是构造函数不同
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; //设备句柄
public boolean appHasCrc16 = true; //app是否支持crc16,一般用默认值
public boolean useFlash = false; //是否是flash设备
/**
* 是否使用其他编码方式
*
* <p>
* 默认false,编码方式如下:<br/>
* - 短文件名: GBK {@link Charset#forName(String)}<br/>
* - 长文件名: 增加"\\U" + Unicode编码数据 + 结束符, {@link Charset#forName(String)}
* 若为true, 则{@link #encodeType} 属性生效
* </p>
*/
public boolean isOtherEncode = false; //是否使用其他编码方式
/**
* 编码方式
*
* <strong>1. 注意需要{@link #isOtherEncode} 为 true, 字段才生效</strong>
*/
public String encodeType = StandardCharsets.UTF_16LE.name(); //默认编码方式
/**
* 指定输出目录路径
* 若为空,则指定输出文件的路径。
*/
public String outputDirPath;
}
1.5.2. 文件读取(设备 -> APP)
对应类 |
功能说明 |
|---|---|
GetFileByClusterTask |
通过文件簇号读取文件任务 |
GetFileByNameTask |
通过文件名读取文件任务 |
1.5.2.1. 通过文件簇号读取文件
推荐读取文件方式
示例代码
//WatchManager是WatchOpImpl的子类,须在1.3配置好sdk
WatchManager watchManager = WatchManager.getInstance();
List<SDCardBean> list = FileBrowseManager.getInstance().getOnlineDev();
if (list.size() < 1) {
//没有在线设备
return;
}
SDCardBean sdCardBean = list.get(0);//获取设备,如果有多个设备,请根据需求获取相应的设备
FileStruct fileStruct = null;//注意fileStructs一定要是在sdCardBean中
int devHandle = sdCardBean.getDevHandler();
int cluster = fileStruct.getCluster();
int offset = 0;
String path = "读取内容的保存路径";
GetFileByClusterTask.Param param = new GetFileByClusterTask.Param(devHandle, 0, cluster, path);
GetFileByClusterTask task = new GetFileByClusterTask(watchManager, param);
task.setListener(new TaskListener() {
@Override
public void onBegin() {
//开始
}
@Override
public void onProgress(int progress) {
//进度回调
}
@Override
public void onFinish() {
//成功
}
@Override
public void onError(int code, String msg) {
//失败
}
@Override
public void onCancel(int reason) {
//取消
}
});
task.start();
1.5.2.2. 通过文件名读取文件
不推荐,需要固件端支持
//WatchManager是WatchOpImpl的子类,须在1.3配置好sdk
WatchManager watchManager = WatchManager.getInstance();
String name = "文件名";
String path = "保存路径";
List<SDCardBean> list = FileBrowseManager.getInstance().getOnlineDev();
if (list.size() < 1) {
//没有在线设备
return;
}
SDCardBean sdCardBean = list.get(0);//获取设备,如果有多个设备,请根据需求获取相应的设备
int devHandle = sdCardBean.getDevHandler();
boolean unicode = false;//文件名是否支持长文件名(长文件采用unicode编码,短文件名使用8+3结构的ASCII编码)
GetFileByNameTask.Param param = new GetFileByNameTask.Param(devHandle,name,path,unicode);
GetFileByNameTask task = new GetFileByNameTask(watchManager,param);
task.setListener(new TaskListener() {
@Override
public void onBegin() {
//开始
}
@Override
public void onProgress(int progress) {
//进度回调
}
@Override
public void onFinish() {
//成功
}
@Override
public void onError(int code, String msg) {
//失败
}
@Override
public void onCancel(int reason) {
//取消
}
});
task.start();
Important
同一个watchManager实例同一时间只能运行一个文件管理的操作, 如果要连续执行多个操作, 需要做串行限制
OTA过程中, 不允许调用文件操作
1.6. 特殊操作(需要设备端配置)
使用以下接口时,请与固件端开发人员沟通是否支持。
1.6.1. 通过文件名删除文件
//WatchManager是WatchOpImpl的子类,须在1.3配置好sdk
WatchManager watchManager = WatchManager.getInstance();
String 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) {
//成功
}
@Override
public void onFailed(BaseError error) {
//失败
}
}));
Important
使用文件管理的相关接口时需要先检查存储设备是否上线
特殊操作需要和固件确认是否支持
OTA过程中, 不允许调用文件操作