需求描述
最近在做蓝牙与android之间互联通信,有个需求,是通过指令,控制蓝牙开启录音,结束录音,录音过程中,将蓝牙传回的数据,转换成pcm文件,然后再做个文件列表,点击播放pcm,包括暂停,重新播放之类的操作。
蓝牙数据转pcm
蓝牙传输的数据,先转换成Byte[],然后再转换成pcm文件,保存到本地。
我们蓝牙协议的真正数据是从字节第4位开始
java
public class ByteKit {
private BitOperator bitOperator;
private BCD8421Operater bcd8421Operater;
private static final ByteKit mInstance = new ByteKit();
public static ByteKit getInstance() {
return mInstance;
}
private ByteKit(){
bitOperator = new BitOperator();
bcd8421Operater = new BCD8421Operater();
}
public float parseFloatFromBytes(byte[] data, int startIndex, int length) {
return this.parseFloatFromBytes(data, startIndex, length, 0f);
}
private float parseFloatFromBytes(byte[] data, int startIndex, int length, float defaultVal) {
try {
// 字节数大于4,从起始索引开始向后处理4个字节,其余超出部分丢弃
final int len = length > 4 ? 4 : length;
byte[] tmp = new byte[len];
System.arraycopy(data, startIndex, tmp, 0, len);
return bitOperator.byte2Float(tmp);
} catch (Exception e) {
e.printStackTrace();
return defaultVal;
}
}
public String parseHexStringFormBytes(byte[] data, int startIndex, int length) {
return this.parseHexStringFormBytes(data, startIndex, length, null);
}
private String parseHexStringFormBytes(byte[] data, int startIndex, int length, String defaultValue) {
try {
byte[] tmp = new byte[length];
System.arraycopy(data, startIndex, tmp, 0, length);
return ConvertUtils.bytes2HexString(tmp);
} catch (Exception e) {
e.printStackTrace();
return defaultValue;
}
}
public String parseStringFromBytes(byte[] data, int startIndex, int lenth) {
return this.parseStringFromBytes(data, startIndex, lenth, null);
}
private String parseStringFromBytes(byte[] data, int startIndex, int lenth, String defaultVal) {
try {
byte[] tmp = new byte[lenth];
System.arraycopy(data, startIndex, tmp, 0, lenth);
return new String(tmp, "gbk");
} catch (Exception e) {
e.printStackTrace();
return defaultVal;
}
}
public String parseBcdStringFromBytes(byte[] data, int startIndex, int lenth) {
return this.parseBcdStringFromBytes(data, startIndex, lenth, null);
}
private String parseBcdStringFromBytes(byte[] data, int startIndex, int lenth, String defaultVal) {
try {
byte[] tmp = new byte[lenth];
System.arraycopy(data, startIndex, tmp, 0, lenth);
return this.bcd8421Operater.bcd2String(tmp);
} catch (Exception e) {
e.printStackTrace();
return defaultVal;
}
}
public int parseIntFromBytes(byte[] data, int startIndex, int length) {
return this.parseIntFromBytes(data, startIndex, length, 0);
}
private int parseIntFromBytes(byte[] data, int startIndex, int length, int defaultVal) {
try {
// 字节数大于4,从起始索引开始向后处理4个字节,其余超出部分丢弃
final int len = length > 4 ? 4 : length;
byte[] tmp = new byte[len];
System.arraycopy(data, startIndex, tmp, 0, len);
return bitOperator.byteToInteger(tmp);
} catch (Exception e) {
e.printStackTrace();
return defaultVal;
}
}
public Long parseLongFromBytes(byte[] data, int startIndex, int length) {
try {
// 字节数大于4,从起始索引开始向后处理4个字节,其余超出部分丢弃
final int len = length > 4 ? 4 : length;
byte[] tmp = new byte[len];
System.arraycopy(data, startIndex, tmp, 0, len);
return bitOperator.fourBytesToLong(tmp);
} catch (Exception e) {
e.printStackTrace();
return 0L;
}
}
public byte[] str2Bcd(String asc) {
int len = asc.length();
int mod = len % 2;
if (mod != 0) {
asc = "0" + asc;
len = asc.length();
}
byte abt[] = new byte[len];
if (len >= 2) {
len = len / 2;
}
byte bbt[] = new byte[len];
abt = asc.getBytes();
int j, k;
for (int p = 0; p < asc.length()/2; p++) {
if ( (abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
j = abt[2 * p] - '0';
} else if ( (abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
j = abt[2 * p] - 'a' + 0x0a;
} else {
j = abt[2 * p] - 'A' + 0x0a;
}
if ( (abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
k = abt[2 * p + 1] - '0';
} else if ( (abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
k = abt[2 * p + 1] - 'a' + 0x0a;
}else {
k = abt[2 * p + 1] - 'A' + 0x0a;
}
int a = (j << 4) + k;
byte b = (byte) a;
bbt[p] = b;
}
return bbt;
}
}
语音协议的数据是从第10位开始,数据长度是4,5两位,做如下处理
java
int dataLength = ByteKit.getInstance().parseIntFromBytes(data, 4, 2);
byte[] result = new byte[dataLength];
System.arraycopy(data, 10, result, 0, result.length);
ibleResponse.CONTROL_AUDIO(result);
byte[]转pcm文件
java
public class ByteToPcmConverter {
public static void convertByteToPcm(byte[] bytes, String filePath) throws IOException {
File file = new File(filePath);
FileOutputStream outputStream = new FileOutputStream(file,true);
outputStream.write(bytes);
outputStream.close();
}
// // 使用示例
// public static void main(String[] args) {
// byte[] bytes = {/* 这里填入你的byte数组 */};
// String pcmFilePath = "/path/to/your/pcmfile.pcm";
// String outputPath= FileUtil.getSDPath(App.getInstance(),"");
// try {
// convertByteToPcm(bytes, pcmFilePath);
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
}
在获取数据之前,比如在点击录音按钮的时候,需要生产文件,文件保存到应用私密空间,在android高版本上,需要特殊处理
java
outputPath= FileUtil.getSDPath(App.getInstance(),name+".pcm");
File file=new File(outputPath);
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
接收数据,并转换,我这还做了个页面提示
java
@Override
public void CONTROL_AUDIO(byte[] bytes) {
try {
ByteToPcmConverter.convertByteToPcm(bytes, outputPath);
File file = new File(outputPath);
if (file.exists() && file.isFile()) {
long length = file.length();
double mb = (double) length / (1024 * 1024);
String format = String.format("%.4f", mb);
tv_write_progress.setText("录音成功,文件大小"+ format +"mb");
}
} catch (IOException e) {
e.printStackTrace();
}
}
java
/**
* 获取SDCard文件路径
* @param ctx
* @return
*/
public static String getSDPath(Context ctx,String fileName) {
return getSDPath(ctx,"",fileName);
}
public static String getSDPath(Context ctx,String path,String fileName) {
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED);// 判断sd卡是否存在
if (sdCardExist) {
if (Build.VERSION.SDK_INT >= 29) {
//Android10之后
sdDir = ctx.getExternalFilesDir(null);
// sdDir= ctx.getExternalCacheDir();
} else {
sdDir= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
}
} else {
sdDir = Environment.getRootDirectory();// 获取跟目录
}
if(!TextUtils.isEmpty(fileName)){
if(!TextUtils.isEmpty(path))
return sdDir.toString()+path+"/"+fileName;
return sdDir.toString()+"/"+fileName;
}
if(!TextUtils.isEmpty(path))
return sdDir.toString()+path;
return sdDir.toString();
}
录音文件页面播放,暂停和文件切换播放
重点是播放pcm文件
java
public class PcmAudioUtils {
private AudioTrack audioTrack;
private String filePath;
private File file;
private int bufferSizeInBytes;
private Thread audioTrackThread;
private int currentPosition;
private double lastTime;
private double elapsedSeconds;//已播放时间
private double audioDurationInSeconds;//总时长
int sampleRateInHz = 8000; // 采样率
int channelConfig = AudioFormat.CHANNEL_OUT_MONO; // 声道配置
int audioFormat = AudioFormat.ENCODING_PCM_16BIT; // 音频格式
boolean pauseTag=false;
private IAudioProgress iAudioProgress;
private String playState="none";
public PcmAudioUtils(String filePath) {
file = new File(filePath);
init();
}
/**
* 初始化
*/
public void init() {
if (!file.exists()) return;
int streamType = AudioManager.STREAM_MUSIC; // 音频流类型
bufferSizeInBytes = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); // 缓冲区大小
/**
* 设置音频信息属性
* 1.设置支持多媒体属性,比如audio,video
* 2.设置音频格式,比如 music
*/
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build();
/**
* 设置音频格式
* 1. 设置采样率
* 2. 设置采样位数
* 3. 设置声道
*/
AudioFormat format = new AudioFormat.Builder()
.setSampleRate(sampleRateInHz)
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setChannelMask(channelConfig)
.build();
audioTrack = new AudioTrack(attributes,format,bufferSizeInBytes,AudioTrack.MODE_STREAM, AudioManager.AUDIO_SESSION_ID_GENERATE);
}
/**
* 停止播放录音,并释放资源
*/
public void stopPlay() {
init();
playState="stopPlay";
if (audioTrack != null) {
audioTrack.release();
}
}
/**
* 暂停
*/
public void pausePlay() {
init();
if (audioTrack != null) {
audioTrack.pause();
}
// if(audioTrackThread!=null){
// audioTrackThread.interrupt();
// }
pauseTag=true;
playState="pausePlay";
}
public void play(){
init();
long currentTimeMillis = SystemClock.elapsedRealtime();
pauseTag=false;
if(audioTrack==null){
return;
}
audioTrack.play();
playState="play";
audioTrackThread= new Thread(() -> {
FileInputStream fileInputStream = null;
lastTime=(double)currentTimeMillis / 1000;
try {
fileInputStream = new FileInputStream(file);
byte[] buffer = new byte[bufferSizeInBytes];
Log.i("PcmAudioUtils", "playAudio: "+bufferSizeInBytes);
if (currentPosition > 0) {
fileInputStream.skip(currentPosition);
}
int read = 0;
while (read != -1&&!pauseTag) {
read = fileInputStream.read(buffer);
//将缓冲区buffer写入audioTrack进行播放
int write = audioTrack.write(buffer, 0, buffer.length);
currentPosition+=write;
// if(iAudioProgress!=null){
// iAudioProgress.playProgress();
// }
elapsedSeconds+=( (double) SystemClock.elapsedRealtime() /1000-lastTime);
// Log.d("AudioTrack", "已播放时间:" +elapsedSeconds + "秒");
}
if(!pauseTag){
audioTrack.stop();
audioTrack.release();
if(iAudioProgress!=null){
iAudioProgress.setStop();
}
currentPosition=0;
}
} catch (Throwable e) {
}
});
audioTrackThread.start();
}
public void setiAudioProgress(IAudioProgress iAudioProgress) {
this.iAudioProgress = iAudioProgress;
}
public interface IAudioProgress{
void playProgress(String progress);
void setStop();
}
public void stop() {
init();
playState="none";
audioTrack.stop();
audioTrack.release();
}
public String getPlayState() {
return playState;
}
}
每次在播放或者暂停的时候,都需要调用一下init()方法,要不然回报未初始化的错误,这块正常播放应该没事,就是切换播放状态,会报错,不知道有没有其他处理办法。
剩下的就简单了,大概逻辑就是:
读取本地存储的pcm文件,在列表上展示,然后点击播放,再次点击暂停,再点击继续播放,播放完成,播放按钮变成未播放,播放途中,点击其他文件播放,正在播放的文件停止。长按文件可以删除
activity_voice_recording.xml
html
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F7F7F7"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
>
<include layout="@layout/layout_toolbar" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="@dimen/dp_10" />
<ImageView
android:id="@+id/iv_audio"
android:layout_width="@dimen/dp_70"
android:layout_height="@dimen/dp_70"
android:layout_marginBottom="20dp"
android:src="@mipmap/icon_start_recording"/>
<TextView
android:id="@+id/tv_write_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginRight="@dimen/dp_10"
android:textColor="@color/text_gray"
tools:text="录音已写入"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
android:layout_margin="@dimen/dp_10"
android:textColor="@color/text_gray"
android:text="*点击列表左侧图标进行播放,长按进行删除"
/>
</LinearLayout>
<RelativeLayout
android:id="@+id/rl_recording"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_recording"
android:layout_width="@dimen/dp_90"
android:layout_height="@dimen/dp_90"
android:layout_marginBottom="220dp"
android:visibility="gone"
android:src="@drawable/audio_anim_image"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
</FrameLayout>
VoiceRecordingActivity.java
java
public class VoiceRecordingActivity extends BaseActivity {
RecyclerView recycler_view;
ImageView iv_audio;
ImageView iv_recording;
TextView tv_write_progress;
RelativeLayout rl_recording;
private List<AudioBean> dataEntityList = new ArrayList<>();
private AudioAdapter adapter;
private String folderName="BLEAUDIO";
private AnimationDrawable animationDrawable;
private String outputPath;
private String platFilePath;//播放音乐的文件地址
private PcmAudioUtils audioPlay = null;
private int selectItemPosition=-1;//已选中的列表项
@Override
public int getLayoutId() {
return R.layout.activity_voice_recording;
}
@Override
public void initViews(Bundle savedInstanceState) {
iv_audio = findViewById(R.id.iv_audio);
iv_recording = findViewById(R.id.iv_recording);
recycler_view = findViewById(R.id.recycler_view);
tv_write_progress= findViewById(R.id.tv_write_progress);
setToolBarInfo("语音录制", true);
// 初始化列表
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recycler_view.setLayoutManager(linearLayoutManager);
recycler_view.setHasFixedSize(true);
recycler_view.setItemAnimator(new DefaultItemAnimator());
recycler_view.addItemDecoration(new SpacesItemDecoration(ConvertUtils.dp2px(this, 5)));
adapter = new AudioAdapter(dataEntityList);
recycler_view.setAdapter(adapter);
adapter.setOnLongClickListener(new OnItemLongClickListener() {
@Override
public void OnLongClickListener(Object o, int position) {
AudioBean audioBean=(AudioBean)o;
new XPopup.Builder(VoiceRecordingActivity.this).asConfirm(getRsString(R.string.hint), getString(R.string.notice_delete),
new OnConfirmListener() {
@Override
public void onConfirm() {
if(audioPlay!=null){
audioPlay.stopPlay();
audioPlay=null;
}
String outputPath= FileUtil.getSDPath(App.getInstance(),audioBean.getAudioInfo());
File file=new File(outputPath);
if(file.exists()){
try {
file.delete();
getFileList();
ToastUtils.show(R.string.operate_successfully);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}).show();
}
});
adapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(Object o, int position) {
AudioBean audioBean=(AudioBean)o;
String filePath=FileUtil.getSDPath(App.getInstance(),audioBean.getAudioInfo());
if(!filePath.equals(platFilePath)){
if(audioPlay!=null){
audioPlay.stop();
}
audioPlay=null;
}
platFilePath =filePath;
if(audioPlay==null){
audioPlay = new PcmAudioUtils(platFilePath);
}
if(selectItemPosition==-1){//初始阶段,没有选中播放,直接播放选中的音频
audioPlay.play();
selectItemPosition=position;
}else if(selectItemPosition==position){//如果点击的是上一次点击过的文件
if(audioPlay.getPlayState().equals("none")){//已经停止播放,重新播放
audioPlay.play();
selectItemPosition=position;
}else if(audioPlay.getPlayState().equals("play")){//已经在播放了,暂停播放
audioPlay.pausePlay();
selectItemPosition=-1;//播放停止,还原成未播放状态
}else if(audioPlay.getPlayState().equals("pausePlay")){//已经暂停播放,继续播放
audioPlay.play();
selectItemPosition=position;
}
}else{//选中的是其他列表项,把正在播放的列表项停止,变成未播放状态,播放选中列表项的文件
audioPlay.stop();
audioPlay=null;
audioPlay = new PcmAudioUtils(platFilePath);
audioPlay.play();
selectItemPosition=position;
}
dataEntityList.get(position).setAudioProgress("");
adapter.setPlayPosition(selectItemPosition);
audioPlay.setiAudioProgress(new PcmAudioUtils.IAudioProgress() {
@Override
public void playProgress(String progress) {
}
@Override
public void setStop() {
final Handler mainHandler = new Handler(Looper.getMainLooper());
// 在子线程中更新数据并刷新RecyclerView
new Thread(new Runnable() {
@Override
public void run() {
// 这里进行数据的更新操作
// updateYourData();
// 使用Handler将刷新操作切换到UI线程
mainHandler.post(new Runnable() {
@Override
public void run() {
// 在UI线程中刷新RecyclerView的适配器
selectItemPosition = -1;//播放停止,还原成未播放状态
adapter.setPlayPosition(selectItemPosition);
audioPlay=null;
}
});
}
}).start();
}
});
}
});
getFileList();
iv_audio.setTag(R.mipmap.icon_start_recording);
iv_audio.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(!BLEUtils.isGetToken()){
ToastUtils.show(R.string.ble_break_retry);
iv_audio.setTag(R.mipmap.icon_start_recording);
iv_audio.setImageResource(R.mipmap.icon_start_recording);
stopAudio();
return;
}
Integer resourceId = (Integer) iv_audio.getTag();
if(resourceId==R.mipmap.icon_start_recording){
iv_audio.setTag(R.mipmap.icon_end_recording);
iv_audio.setImageResource(R.mipmap.icon_end_recording);
startAudio();
}else{
iv_audio.setTag(R.mipmap.icon_start_recording);
iv_audio.setImageResource(R.mipmap.icon_start_recording);
stopAudio();
}
}
});
}
private void startAudio(){
iv_recording.setVisibility(View.VISIBLE);
tv_write_progress.setVisibility(View.VISIBLE);
animationDrawable = (AnimationDrawable) iv_recording.getDrawable();
//直接就开始执行
animationDrawable.start();
String address = PreferencesUtils.getString("address");
String name= address+"--"+ DateUtils.getCurrentTime();
//保存到本地
outputPath= com.smart.bing.utils.FileUtil.getSDPath(App.getInstance(),name+".pcm");
File file=new File(outputPath);
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if(BLEUtils.isGetToken()){
LmAPI.CONTROL_AUDIO((byte) 0x1);
}
}
private void stopAudio(){
iv_recording.setVisibility(View.GONE);
tv_write_progress.setVisibility(View.GONE);
if(animationDrawable!=null){
animationDrawable.stop();
animationDrawable=null;
}
if(BLEUtils.isGetToken()){
LmAPI.CONTROL_AUDIO((byte) 0x0);
}
getFileList();
}
public void getFileList() {
dataEntityList.clear();
String outputPath=FileUtil.getSDPath(App.getInstance(),"");
File folder = new File(outputPath);
File[] files = folder.listFiles();
if (files != null) {
Arrays.sort(files, new Comparator<File>() {
@Override
public int compare(File file1, File file2) {
return Long.compare(file2.lastModified(), file1.lastModified());
}
});
for (File file : files) {
String fileName = file.getName();
String filePath = file.getAbsolutePath();
// 处理文件逻辑,比如打印文件名和文件路径
Log.d("File", "File Name: " + fileName + ", File Path: " + filePath);
String fileExtension = file.getName().substring(file.getName().lastIndexOf(".") + 1);
if("pcm".equals(fileExtension)){
AudioBean audioBean=new AudioBean();
audioBean.setAudioInfo(fileName);
audioBean.setAudioProgress("");
dataEntityList.add(audioBean);
}
}
}
adapter.notifyDataSetChanged();
}
@Override
protected void onDestroy() {
super.onDestroy();
//关闭录音
if(BLEUtils.isGetToken()){
LmAPI.CONTROL_AUDIO((byte) 0x0);
}
}
@Override
protected void onPause() {
super.onPause();
if(audioPlay!=null){
audioPlay.stopPlay();
audioPlay=null;
}
}
@Override
public void CONTROL_AUDIO(byte[] bytes) {
try {
ByteToPcmConverter.convertByteToPcm(bytes, outputPath);
File file = new File(outputPath);
if (file.exists() && file.isFile()) {
long length = file.length();
double mb = (double) length / (1024 * 1024);
String format = String.format("%.4f", mb);
tv_write_progress.setText("录音成功,文件大小"+ format +"mb");
}
} catch (IOException e) {
e.printStackTrace();
}
}
这一块有个坑,是在子线程更新adapter,直接更新会无效,需要实现子线程到主线程的转换。重点代码是:
java
final Handler mainHandler = new Handler(Looper.getMainLooper());
// 在子线程中更新数据并刷新RecyclerView
new Thread(new Runnable() {
@Override
public void run() {
// 这里进行数据的更新操作
// updateYourData();
// 使用Handler将刷新操作切换到UI线程
mainHandler.post(new Runnable() {
@Override
public void run() {
// 在UI线程中刷新RecyclerView的适配器
selectItemPosition = -1;//播放停止,还原成未播放状态
adapter.setPlayPosition(selectItemPosition);
audioPlay=null;
}
});
}
}).start();
AudioAdapter.java
java
public class AudioAdapter extends RecyclerView.Adapter<AudioAdapter.StrokeHolder> {
private OnItemClickListener onItemClickListener;
private OnItemLongClickListener onLongClickListener;
private List<AudioBean> dataEntityList = new ArrayList<>();
private int playPosition=-1;//显示播放按钮的列表项
public AudioAdapter(List<AudioBean> dataEntityList) {
this.dataEntityList = dataEntityList;
}
@Override
public StrokeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = View.inflate(parent.getContext(), R.layout.item_audio_layout, null);
return new StrokeHolder(view, onItemClickListener);
}
@Override
public void onBindViewHolder(StrokeHolder holder, int position) {
AudioBean resultEntity = dataEntityList.get(position);
holder.setData(resultEntity);
if(playPosition==position){
holder.ivAudioStart.setImageResource(R.mipmap.icon_end);
holder.ivAudioStart.setTag(R.mipmap.icon_end); // 存储资源 ID
}else{
holder.ivAudioStart.setImageResource(R.mipmap.icon_start);
holder.ivAudioStart.setTag(R.mipmap.icon_start); // 存储资源 ID
}
}
@Override
public int getItemCount() {
return dataEntityList.size();
}
@SuppressLint("NotifyDataSetChanged")
public void setPlayPosition(int position){
playPosition=position;
notifyDataSetChanged();
}
public AudioBean getItemBean(int position) {
return dataEntityList.get(position);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public void setOnLongClickListener(OnItemLongClickListener onLongClickListener) {
this.onLongClickListener = onLongClickListener;
}
public void updateData(AudioBean audioBean) {
if (!dataEntityList.contains(audioBean)) {
dataEntityList.add(audioBean);
notifyDataSetChanged();
}
}
public void clearData() {
dataEntityList.clear();
notifyDataSetChanged();
}
class StrokeHolder extends RecyclerView.ViewHolder implements View.OnClickListener ,View.OnLongClickListener{
TextView tvAudioInfo;
TextView tvAudioProgress;
ImageView ivAudioStart;
OnItemClickListener onItemClick;
public StrokeHolder(View itemView, OnItemClickListener onItemClickListener) {
super(itemView);
tvAudioInfo = (TextView) itemView.findViewById(R.id.tv_audio_info);
tvAudioProgress = (TextView) itemView.findViewById(R.id.tv_audio_progress);
ivAudioStart = itemView.findViewById(R.id.iv_audio_start);
itemView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
this.onItemClick = onItemClickListener;
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
public void setData(AudioBean resultEntity) {
tvAudioInfo.setText(resultEntity.getAudioInfo());
tvAudioProgress.setText(resultEntity.getAudioProgress());
}
@Override
public void onClick(View v) {
if (onItemClick != null) {
onItemClick.onItemClick(dataEntityList.get(getPosition()), getPosition());
}
}
@Override
public boolean onLongClick(View v) {
if(onLongClickListener !=null){
onLongClickListener.OnLongClickListener(dataEntityList.get(getPosition()), getPosition());
}
return true;
}
}
}