欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 会展 > android 蓝牙语音转换成pcm文件,进行播放暂停停止操作

android 蓝牙语音转换成pcm文件,进行播放暂停停止操作

2024/10/26 11:03:36 来源:https://blog.csdn.net/jifashihan/article/details/142629072  浏览:    关键词:android 蓝牙语音转换成pcm文件,进行播放暂停停止操作

需求描述

最近在做蓝牙与android之间互联通信,有个需求,是通过指令,控制蓝牙开启录音,结束录音,录音过程中,将蓝牙传回的数据,转换成pcm文件,然后再做个文件列表,点击播放pcm,包括暂停,重新播放之类的操作。

蓝牙数据转pcm

蓝牙传输的数据,先转换成Byte[],然后再转换成pcm文件,保存到本地。
我们蓝牙协议的真正数据是从字节第4位开始

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两位,做如下处理

  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文件

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高版本上,需要特殊处理

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);}}

接收数据,并转换,我这还做了个页面提示

 @Overridepublic 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();}}
    /*** 获取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文件

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

<?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"
><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:gravity="center"><include layout="@layout/layout_toolbar" /><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recycler_view"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:padding="@dimen/dp_10" /><ImageViewandroid: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"/><TextViewandroid: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="录音已写入"/><TextViewandroid: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><RelativeLayoutandroid:id="@+id/rl_recording"android:layout_width="match_parent"android:layout_height="match_parent"><ImageViewandroid: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

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;//已选中的列表项@Overridepublic int getLayoutId() {return R.layout.activity_voice_recording;}@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic void playProgress(String progress) {}@Overridepublic void setStop() {final Handler mainHandler = new Handler(Looper.getMainLooper());// 在子线程中更新数据并刷新RecyclerViewnew Thread(new Runnable() {@Overridepublic void run() {// 这里进行数据的更新操作// updateYourData();// 使用Handler将刷新操作切换到UI线程mainHandler.post(new Runnable() {@Overridepublic 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() {@Overridepublic 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>() {@Overridepublic 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();}@Overrideprotected void onDestroy() {super.onDestroy();//关闭录音if(BLEUtils.isGetToken()){LmAPI.CONTROL_AUDIO((byte) 0x0);}}@Overrideprotected void onPause() {super.onPause();if(audioPlay!=null){audioPlay.stopPlay();audioPlay=null;}}@Overridepublic 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,直接更新会无效,需要实现子线程到主线程的转换。重点代码是:

final Handler mainHandler = new Handler(Looper.getMainLooper());// 在子线程中更新数据并刷新RecyclerViewnew Thread(new Runnable() {@Overridepublic void run() {// 这里进行数据的更新操作// updateYourData();// 使用Handler将刷新操作切换到UI线程mainHandler.post(new Runnable() {@Overridepublic void run() {// 在UI线程中刷新RecyclerView的适配器selectItemPosition = -1;//播放停止,还原成未播放状态adapter.setPlayPosition(selectItemPosition);audioPlay=null;}});}}).start();

AudioAdapter.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;}@Overridepublic StrokeHolder onCreateViewHolder(ViewGroup parent, int viewType) {View view = View.inflate(parent.getContext(), R.layout.item_audio_layout, null);return new StrokeHolder(view, onItemClickListener);}@Overridepublic 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}}@Overridepublic 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());}@Overridepublic void onClick(View v) {if (onItemClick != null) {onItemClick.onItemClick(dataEntityList.get(getPosition()), getPosition());}}@Overridepublic boolean onLongClick(View v) {if(onLongClickListener !=null){onLongClickListener.OnLongClickListener(dataEntityList.get(getPosition()), getPosition());}return true;}}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com