网易云私信能微信如何发送私信语音吗? 互相关注的好友之间什么时候能开发语音功能呢?

More than a coder...
Android实现发送语音,可限制语音时间,对用户手势判断
最近公司项目中需要用到聊天功能,在通过对比网易云信和环信之后呢还是选择了使用环信。虽然我很喜欢网易的云音乐,但环信使用起来确实比较简单,就选择了它,今天这篇文章主要是讲的关于语音聊天的功能的实现。先来看一下我做的效果图吧~
由于为了录制这个动态图,我用的是模拟器,所以在录制过程中的麦克风中间的波形没有波动,但是使用真机的话麦克风的波形是可以随着说话的音量波动起来的。在用户松开按钮后将录音文件保存在本地,没做其他操作,如果你也和我一样正在做这一块的话可以尝试去将这个功能去完善起来。
首先呢来整理一下思路,用户在按住按钮之后会进行调用麦克风进行录音,松开按钮后将语音文件保存在本地。虽然看起来比较简单,但是为了实现这个功能,我也参考了其他大神的方法,也花了不少时间,觉得写的不错的话,就点个赞呗,嘿嘿嘿。~
闲话不多说,现在来看看我是如何实现的吧。
一共写了三个类:
首先自定义了一个AudioRecorderButton继承Button,重写了onTouch事件:
* 控制录音Button
* 1、重写onTouchEvent;(changeState方法、wantToCancel方法、reset方法);
* 2、编写AudioDialogManage、并与该类AudioRecorderButton进行整合;
* 3、编写AudioManage、并与该类AudioRecorderButton进行整合;
public class AudioRecorderButton extends Button implements AudioManage.AudioStateListener {
* AudioRecorderButton的三个状态
private static final int STATE_NORMAL = 1;
//默认状态
private static final int STATE_RECORDERING = 2;
//录音状态
private static final int STATE_WANT_TO_CALCEL = 3;
//取消状态
private int mCurState = STATE_NORMAL;
// 当前录音状态
private boolean isRecordering =
// 是否已经开始录音
private boolean mR
// 是否触发onLongClick
private static final int DISTANCE_Y_CANCEL = 50;
private AudioDialogManage audioDialogM
private AudioManage mAudioM
* 正常录音完成后的回调
public interface AudioFinishRecorderListener{
void onFinish(int seconds, String FilePath);
private AudioFinishRecorderListener mL
public void setAudioFinishRecorderListener(AudioFinishRecorderListener listener){
this.mListener=
//构造方法
public AudioRecorderButton(Context context) {
super(context, null);
// TODO Auto-generated constructor stub
public AudioRecorderButton(final Context context, AttributeSet attrs) {
super(context, attrs);
audioDialogManage = new AudioDialogManage(getContext());
String dir = Environment.getExternalStorageDirectory()
+ "/kairui/VoiceCache";
// 此处需要判断是否有存储卡(外存)
mAudioManage = AudioManage.getInstance(dir);
mAudioManage.setOnAudioStateListener(this);
setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View v) {
// 真正显示应该在audio end prepared以后
mAudioManage.prepareAudio();
mAudioManage.setOnAudioStatusUpdateListener(new AudioManage.OnAudioStatusUpdateListener() {
//录音中....db为声音分贝,time为录音时长
public void onUpdate(double db, long time) {
//根据分贝值来设置录音时话筒图标的上下波动
audioDialogManage.mIcon.getDrawable().setLevel((int) (3000 + 6000 * db / 100));
// TODO Auto-generated constructor stub
* 复写onTouchEvent
* @see android.widget.TextView#onTouchEvent(android.view.MotionEvent)
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
//获取当前Action
int x = (int) event.getX();
//获取当前的坐标
int y = (int) event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
changeState(STATE_RECORDERING);
case MotionEvent.ACTION_MOVE:
// 已经开始录音状态时,根据X、Y的坐标,判断是否想要取消
if (isRecordering) {
if (wantToCancel(x, y)) {
changeState(STATE_WANT_TO_CALCEL);
changeState(STATE_RECORDERING);
case MotionEvent.ACTION_UP:
if (!mReady) {
//没有触发onLongClick
return super.onTouchEvent(event);
if (!isRecordering || mTime & 900) {
//录音时间过短
audioDialogManage.tooShort();
mAudioManage.cancel();
mHandler.sendEmptyMessageDelayed(MSG_DIALOG_DISMISS, 1300);// 延迟,1.3秒以后关闭“时间过短对话框”
else if (mCurState == STATE_RECORDERING) { //正常录制结束
audioDialogManage.dismissDialog();
// release
mAudioManage.release();
// callbackToAct
// 正常录制结束,回调录音时间和录音文件完整路径——在播放的时候需要使用
if(mListener!=null){
mListener.onFinish(mTime /1000, mAudioManage.getCurrentFilePath());
} else if (mCurState == STATE_WANT_TO_CALCEL) {
audioDialogManage.dismissDialog();
mAudioManage.cancel();
return super.onTouchEvent(event);
* 恢复状态以及一些标志位
private void reset() {
isRecordering =
//是否触发onLongClick
mTime = 0;
changeState(STATE_NORMAL);
private boolean wantToCancel(int x, int y) {
// 判断手指的滑动是否超出范围
if (x & 0 || x & getWidth()) {
if (y & -DISTANCE_Y_CANCEL || y & getHeight() + DISTANCE_Y_CANCEL) {
* 改变Button的背景和文本、展示不同状态的录音提示对话框
* @param state
private void changeState(int state) {
if (mCurState != state) {
mCurState =
switch (state) {
case STATE_NORMAL:
setBackgroundResource(R.drawable.send_speech_btn_normal_style);
setText(R.string.push_to_speak);
case STATE_RECORDERING:
setBackgroundResource(R.drawable.send_speech_btn_pres_style);
setText(R.string.release_to_send);
if (isRecordering) {
// 更新Dialog.recording()
audioDialogManage.recording();
case STATE_WANT_TO_CALCEL:
setBackgroundResource(R.drawable.send_speech_btn_pres_style);
setText(R.string.release_to_cancel_send);
// 更新Dialog.wantCancel()
audioDialogManage.wantToCancel();
* 实现“准备完毕”接口
* (non-Javadoc)
public void wellPrepared() {
// TODO Auto-generated method stub
mHandler.sendEmptyMessage(MSG_AUDIO_PREPARED);
private static final int MSG_AUDIO_PREPARED = 0x110;
//准备完全
private static final int MSG_CURRENT_TIME = 0x111;
//当前语音时长
private static final int MSG_DIALOG_DISMISS = 0x112;
//销毁对话框
private static final int MSG_COUNT_DOWN_DONE = 0x113;
//录音倒计时结束
* 接收子线程数据,并用此数据配合主线程更新UI
* Handler运行在主线程(UI线程)中,它与子线程通过Message对象传递数据。
* Handler接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,把这些消息放入主线程队列中,配合主线程进行更新UI。
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_AUDIO_PREPARED:
//216:mHandler.sendEmptyMessage(MSG_AUDIO_PREPARED);
audioDialogManage.showRecorderingDialog();
isRecordering =
//已经在录制,同时开启一个获取音量、并且计时的线程
new Thread(mUpdateCurTimeRunnable).start();
case MSG_CURRENT_TIME:
//265:mHandler.sendEmptyMessage(MSG_VOICE_CHANGE);
audioDialogManage.updateCurTime(TimeUtils.countDown(mTime));
//这里在Handler里面处理DIALOG_DIMISS,是因为想让该对话框显示一段时间,延迟关闭,——详见125行
case MSG_DIALOG_DISMISS:
//125:mHandler.sendEmptyMessageDelayed(MSG_DIALOG_DISMISS, 1300);
audioDialogManage.dismissDialog();
//处理录音时间结束
case MSG_COUNT_DOWN_DONE:
mAudioManage.release();
// callbackToAct
// 正常录制结束,回调录音时间和录音文件完整路径——在播放的时候需要使用
if(mListener!=null){
mListener.onFinish(mTime /1000, mAudioManage.getCurrentFilePath());
audioDialogManage.dismissDialog();
private int mT
//开始录音计时,计时;(在reset()中置空) 单位为毫秒
* 更新当前录音时长的runnable
private Runnable mUpdateCurTimeRunnable = new Runnable() {
public void run() {
while (isRecordering) {
Thread.sleep(100);
mTime += 100;
mHandler.sendEmptyMessage(MSG_CURRENT_TIME);
if(mTime == 60 * 1000){
mHandler.sendEmptyMessage(MSG_COUNT_DOWN_DONE);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
接下来是AudioDialogManage:
* 录制语音弹窗管理类
public class AudioDialogManage {
private Dialog mD
public ImageView mI
//麦克风及删除图标
private TextView mT
//录音时长
private TextView mL
//录音提示文字
private Context mC
public AudioDialogManage(Context context) {
this.mContext =
* 默认的对话框的显示
public void showRecorderingDialog() {
mDialog = new Dialog(mContext, R.style.Theme_AudioDialog);
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(
R.layout.voicenotes_recorder_dialog, null);
mDialog.setContentView(view);
mIcon = (ImageView) mDialog.findViewById(R.id.recorder_dialog_icon);
mTime = (TextView) mDialog.findViewById(R.id.recorder_dialog_time_tv);
mLabel = (TextView) mDialog.findViewById(R.id.recorder_dialog_label);
mDialog.show();
//下面在显示各种对话框时,mDialog已经被构造,只需要控制ImageView、TextView的显示即可
* 正在录音时,Dialog的显示
public void recording() {
if (mDialog != null && mDialog.isShowing()) {
mIcon.setVisibility(View.VISIBLE);
mTime.setVisibility(View.VISIBLE);
mLabel.setVisibility(View.VISIBLE);
mIcon.setImageResource(R.drawable.record_microphone);
mLabel.setBackgroundColor(Color.parseColor("#"));
mLabel.setText(R.string.slide_up_cancel_send);
* 取消录音提示对话框
public void wantToCancel() {
if (mDialog != null && mDialog.isShowing()) {
mIcon.setVisibility(View.VISIBLE);
mTime.setVisibility(View.GONE);
mLabel.setVisibility(View.VISIBLE);
mIcon.setImageResource(R.drawable.delete_speech_anim_list);
mLabel.setBackgroundColor(Color.parseColor("#AF2831"));
mLabel.setText(R.string.release_to_cancel_send);
* 录音时间过短
public void tooShort() {
if (mDialog != null && mDialog.isShowing()) {
mIcon.setVisibility(View.VISIBLE);
mTime.setVisibility(View.GONE);
mLabel.setVisibility(View.VISIBLE);
mIcon.setImageResource(R.drawable.speech_is_too_short);
mLabel.setBackgroundColor(Color.parseColor("#"));
mLabel.setText("说话时间太短");
* mDialog.dismiss();
public void dismissDialog() {
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss();
* 更新显示当前录音秒数
* @param time
public void updateCurTime(String time) {
if (mDialog != null && mDialog.isShowing()) {
mTime.setText(time);
提示框的xml代码:
&LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"&
&LinearLayout
android:background="@drawable/record_microphone_bj"
android:layout_width="140dp"
android:layout_height="140dp"
android:gravity="center"
android:orientation="vertical"&
&RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"&
&ImageView
android:layout_centerInParent="true"
android:id="@+id/recorder_dialog_icon"
android:layout_width="55dp"
android:layout_height="65dp"
android:src="@drawable/record_microphone"
android:visibility="visible" /&
android:id="@+id/recorder_dialog_time_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:layout_alignBottom="@id/recorder_dialog_icon"
android:layout_toRightOf="@id/recorder_dialog_icon"
android:textColor="@color/white"
android:text="60''"/&
&/RelativeLayout&
android:id="@+id/recorder_dialog_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textSize="14sp"
android:gravity="center"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:text="@string/slide_up_cancel_send"
android:textColor="@color/white" /&
&/LinearLayout&
&/LinearLayout&
最后是AudioManage代码:
* Audio管理类
public class AudioManage {
private MediaRecorder mMediaR
//MediaRecorder可以实现录音和录像。需要严格遵守API说明中的函数调用先后顺序.
private String mD
// 文件夹的名称
private String mCurrentFileP
private static AudioManage mI
private boolean isP // 标识MediaRecorder准备完毕
private AudioManage(String dir) {
private OnAudioStatusUpdateListener audioStatusUpdateL
private long startT
* 回调“准备完毕”
* @author songshi
public interface AudioStateListener {
void wellPrepared();
// prepared完毕
public AudioStateListener mL
public void setOnAudioStateListener(AudioStateListener audioStateListener) {
mListener = audioStateL
* 使用单例实现 AudioManage
* @param dir
//DialogManage主要管理Dialog,Dialog主要依赖Context,而且此Context必须是Activity的Context,
//如果DialogManage写成单例实现,将是Application级别的,将无法释放,容易造成内存泄露,甚至导致错误
public static AudioManage getInstance(String dir) {
if (mInstance == null) {
synchronized (AudioManage.class) {
if (mInstance == null) {
mInstance = new AudioManage(dir);
* 准备录音
public void prepareAudio() {
isPrepared =
File dir = new File(mDir);
if (!dir.exists()) {
dir.mkdirs();
String fileName = GenerateFileName(); // 文件名字
File file = new File(dir, fileName);
// 路径+文件名字
//MediaRecorder可以实现录音和录像。需要严格遵守API说明中的函数调用先后顺序.
mMediaRecorder = new MediaRecorder();
mCurrentFilePath = file.getAbsolutePath();
mMediaRecorder.setOutputFile(file.getAbsolutePath());
// 设置输出文件
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
// 设置MediaRecorder的音频源为麦克风
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
// 设置音频的格式
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
// 设置音频的编码为AMR_NB
mMediaRecorder.prepare();
mMediaRecorder.start();
startTime = System.currentTimeMillis();
updateMicStatus();
isPrepared = // 准备结束
if (mListener != null) {
mListener.wellPrepared();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
* 生成文件名称
private String GenerateFileName() {
// TODO Auto-generated method stub
return UUID.randomUUID().toString() + ".amr"; // 音频文件格式 ,随机生成名字
return TimeUtils.getCurrentTime() + ".amr";
// 生成带有时间的名字
* 释放资源
public void release() {
mMediaRecorder.stop();
mMediaRecorder.release();
mMediaRecorder =
* 取消(释放资源+删除文件)
public void cancel() {
release();
if (mCurrentFilePath != null) {
File file = new File(mCurrentFilePath);
file.delete();
//删除录音文件
mCurrentFilePath =
public String getCurrentFilePath() {
// TODO Auto-generated method stub
return mCurrentFileP
private int BASE = 1;
private int SPACE = 100;// 间隔取样时间
public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener audioStatusUpdateListener) {
this.audioStatusUpdateListener = audioStatusUpdateL
private final Handler mHandler = new Handler();
private Runnable mUpdateMicStatusTimer = new Runnable() {
public void run() {
updateMicStatus();
* 更新麦克状态
private void updateMicStatus() {
if (mMediaRecorder != null) {
double ratio = (double)mMediaRecorder.getMaxAmplitude() / BASE;
if (ratio & 1) {
db = 20 * Math.log10(ratio);
if(null != audioStatusUpdateListener) {
audioStatusUpdateListener.onUpdate(db,System.currentTimeMillis()-startTime);
mHandler.postDelayed(mUpdateMicStatusTimer, SPACE);
public interface OnAudioStatusUpdateListener {
* 录音中...
* @param db 当前声音分贝
* @param time 录音时长
public void onUpdate(double db,long time);
然后再放上Dialog的style代码:
&!-- 录音对话框 &style name="Theme_AudioDialog"& --&
&style name="Theme_AudioDialog" parent="@android:style/Theme.Dialog"&
&item name="android:windowBackground"&@android:color/transparent&/item&
&item name="android:windowFrame"&@null&/item&
&item name="android:windowIsFloating"&true&/item&
&item name="android:windowIsTranslucent"&true&/item&
&item name="android:backgroundDimEnabled"&false&/item&
最后呢记得在使用的过程中调用以下方法:
//发送录音结束接口
sendSpeechBtn.setAudioFinishRecorderListener(new AudioRecorderButton.AudioFinishRecorderListener() {
public void onFinish(int seconds, String FilePath) {
ToastUtils.showShort(ChattingActivity.this,"语音文件为:"+FilePath+"时长:"+seconds);
//拿到文件地址和时长后就可以去做发送语音的操作了
以上就是今天跟大家分享的语音功能的全部代码了,目前还未完成将发送的语音文件显示到列表上以及点击list
Item之后可以去播放语音文件,因为急着要去完成别的功能,这个就过几天再去实现。需要源码的话就说一下,我好先整理整理,毕竟全部写在了公司的项目中。如果你在使用的过程中遇到问题欢迎私信我,说不定我们之间还能发生些什么,嘿嘿嘿~(●ˇ?ˇ●)对了,要实现麦克风图形可以波动的效果记得使用类似这样的图片
好了,就先写到这里了。
没有更多推荐了,新浪微博中与好友发的私信别人会看到吗
  新浪微博的私信就是别人发送给您或者您发送给别人的私人信息,只有联系人双发才可以看到,别人是看不到的。目前微博私信还支持图片和文件传递功能。  新浪微博是一个由新浪网推出,提供微型博客服务的类Twitter网站。用户可以通过网页、页面、手机短信、彩信发布消息或上传图片。新浪可以把微博理解为&微型博客&或者&一句话博客&。用户可以将自己看到的、听到的、想到的事情写成一句话,或发一张图片,通过电脑或者手机随时随地分享给朋友,一起分享、讨论。用户还可以关注自己的朋友,即时看到朋友们发布的信息。  新浪微博于日开始内测。9月25日,新浪微博正式添加了@功能以及私信功能,此外还提供&评论&和&转发&功能,供用户交流。目前优秀的微博桌面客户端有微波炉、AIR微博(官方)、Wing微博。  目前用户可以通过网页、WAP网,手机短信彩信、手机客户端(包括NOKIA S60系统、iPhone(系统)、Android系统、Windows Phone系统)、SWISEN、MSN绑定等多种方式更新自己的微博。每条微博字数限制为140字,提供插入单张图片、视频地址、音乐功能。
最新更新栏目
您可能喜欢
大家都在搜&>&&>&&>&&>&正文
私信是一款免费的时尚语音聊天软件,拥有出色的语音聊天功能,可搭配文字、图片、炫酷表情快速发送,还能发起群组多人聊天,让您更加方便的与朋友实时沟通。主要功能介绍:支持人人帐号登录,方便找到好友聊天匹配通讯录,智能帮您找到更多好友群聊功能,简简单单就能与朋友们随时沟通语音聊天,解放拇指,沟通更轻松图片照片,即拍即传,无需等待炫酷表情,文字消息,极速送达手机电脑在线一目了然,互动聊天更随心特别关注,让好友“尽在掌握中”
价格:$0.00类别:社交更新:日当前版本:2.1.4大小:6.8 MB语言:中文开发商:Beijing Qian Xiang Tiancheng Technology Development Co.,Ltd.系统要求:与 iPhone、iPod touch、iPad 兼容。 需要 iOS 4.3 或更高版本用户评价:当前版本共有11位用户评价,平均评分为1.5;共有518位用户评价此应用,平均评分为1.5。
私信更新内容
私信v2.1.4更新内容:&修复了收到push后点击进入无消息内容的问题&其他问题修复
提示:支持键盘“← →”键翻页百度知道里 发私信消息可以语音说话吗_百度知道
百度知道里 发私信消息可以语音说话吗
我有更好的答案
百度知道里 发私信消息可以语音说话。
采纳率:98%
那你和我发呀
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。网易云音乐不关注歌手只收藏,有新歌还会发送私信吗_百度知道
网易云音乐不关注歌手只收藏,有新歌还会发送私信吗
我有更好的答案
为您推荐:
其他类似问题
云音乐的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。

我要回帖

更多关于 微博私信发送失败 的文章

 

随机推荐