Android 微信语音功能

首先大家可以参考一下这个大神的例子,我写的也是在他的基础上改编的,多了数据库,下拉刷新加载数据,左右2种布局写入同一个ListView

这是他的代码  :http://download.csdn.net/detail/u013982769/8680185


一  数据库

有关数据库方面的知识,相信大家都不陌生,假如有不会的可以百度,或者参考我写的数据库方面的知识,很简洁:Android 数据库简单操作

/**
	 * 当MyDBHelper对象被创建时,该方法被调用,该方法主要是来作一些初始化的数据,比如建表操作
	 */
	@Override
	public void onCreate(SQLiteDatabase db) {
		Log.d("sqlite", "***MyDBHelper's onCreate()....");
		// 创建表
		String createSQL = "create table come(id integer primary key,type int,time float not null,filePathString varchar(20) not null)";
		db.execSQL(createSQL);
	}
上面是建表语句,字段十分的简单,主要是主键id,通话时间以及路径。接下来就开始写有关对数据库的操作,主要是添加语音和查看。我们先看一下代码,下面的代码只要用于判断语音是否存储成功,成功返回true,否则为false:

/**
	 * 分页查询
	 * 
	 * @param currentPage 当前页
	 * @param pageSize 每页显示的记录
	 * @return 当前页的记录
	 */
	public List<RecorderUtil> find(int currentPage, int pageSize) {
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		String sql = "select * from come limit ?,?";
		Cursor cursor = db.rawQuery(sql, new String[] { String.valueOf(currentPage), String.valueOf(pageSize) });
		while (cursor.moveToNext()) {
			RecorderUtil sRecorderUtil = new RecorderUtil(1, cursor.getFloat(cursor.getColumnIndex("time")),
					cursor.getString(cursor.getColumnIndex("filePathString")));
			mDatas.add(sRecorderUtil);
		}
		return mDatas;
	}

在接下来的开发中发现光依靠这个方法无法实现我们的目的,所以还需要知道语音的数量,我们看一下代码:
/**
	 * 查询记录的总数
	 * @return 当前页的数量
	 */
	public int getCount() {
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		Cursor cursor = db.rawQuery("select count(*) from come", null);
		cursor.moveToFirst();
		int count = cursor.getInt(0);// 第0个下标参数
		cursor.close();
		return count;
	}

有关数据库方面的代码其实就这么多,不需要把增删改查全部写完,只需要写出自己需要的部分。




二 下拉刷新功能:

使用下拉刷新,我用到的是PullToRefreshListView,这位大神已经很详细的讲解了如何使用PullToRefreshListView:http://blog.csdn.net/harvic880925/article/details/17680305

其实如果你不嫌麻烦,可以com.handmark.pulltorefresh.library路径下的所有代码全部导入你的项目中,也是可以使用的。

<com.handmark.pulltorefresh.library.PullToRefreshListView
        xmlns:ptr="http://schemas.android.com/apk/res-auto"
        android:id="@+id/speak_list"
        android:layout_width="match_parent"
        android:layout_height="300dip"
        android:drawSelectorOnTop="false"
        android:scrollbarAlwaysDrawVerticalTrack="true"
        android:background="#ebebeb"
        android:cacheColorHint="@android:color/transparent"
        android:clipToPadding="false"
        android:divider="@null"
        android:dividerHeight="10dp"
        android:paddingBottom="1dp"
        android:transcriptMode="normal"
        ptr:ptrMode="pullFromStart"
        ptr:ptrOverScroll="false" />


这是引用代码,其实可以把他当做是一个ListView使用,那么我们首先希望在我们进入语音app的时候,是有数据的,而不是永远都是空的,这样就需要我们从数据库拉数据出来,

private ComeModle mComeModle ;
private int allRecorders = 0;  //全部记录数
private List<RecorderUtil> mDatas = new ArrayList<RecorderUtil>();

try {
			mComeModle= new ComeModle(MainActivity.this);
			allRecorders=mComeModle.getCount();
			mDatas=mComeModle.find((allRecorders-5),5);
			Log.d(TAG, "mDatas count: " + mDatas.size());
			mlistview.setAdapter(mAdapter);
		} catch (Exception e) {
			Log.i("exception", e.toString());
		}
先定义一些参数,然后调用刚才调用刚才查询的方法,通过总数allRecorders,控制显示的位子,我们希望出现的最新的数据,而不是最上面id为一的数据,这是通过limit来实现的,limit的使用,文档有说明,中文的意思是 指定偏移量和获取的记录数,相当于select语句limit关键字后面的部分。
进去看到原有的数据还不够,我们该如何查看之前的数据呢?PullToRefreshListView本身就提供了下拉刷新的功能,我们需要做的是连一个接口实现他的方法,代码如下:

public class MainActivity extends Activity implements OnRefreshListener2<ListView> {

}

我们通过OnRefreshListener2<ListView>重写下拉刷新,代码如下:

/**
	 * @Description 下拉加载数据
	 * @param refreshView
	 */
	@Override
	public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) {
		
		// 获取消息
		refreshView.postDelayed(new Runnable() {
			@Override
			public void run() {

				if (mAdapter.getCount() > 0) {
					mAdapter.clearItem();
				}
				try {
					mComeModle= new ComeModle(MainActivity.this);
					allRecorders=mComeModle.getCount();
					//计算总页数
					int pageSize=(allRecorders+5-1)/5;
					if(MSG_ADD<=pageSize){
						mDatas.addAll(0,mComeModle.find((allRecorders-5*(MSG_ADD++)),5));
					}else {
						Log.d(TAG, "jia zai wan cheng");
					}
					
					Log.d(TAG, String.valueOf(MSG_ADD));
					Log.d(TAG, String.valueOf(pageSize));
					Log.d(TAG, String.valueOf(mDatas.size()));
				} catch (Exception e) {
					Log.i("exception", e.toString());
				}
				mAdapter = new RecorderBaseAdapter(MainActivity.this, mDatas);
				mlistview.setAdapter(mAdapter);
				ListView mlist = mlistview.getRefreshableView();
				if (!(mlist).isStackFromBottom()) {
					mlist.setStackFromBottom(true);
				}
				mlist.setStackFromBottom(false);
				refreshView.onRefreshComplete();
			}
		}, 200);

	}

	/**
	 * @Description 下拉加载数据
	 * @param refreshView
	 */
	@Override
	public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {

	}

首先我们计算了分页后的总页数,其中MSG_ADD是自增的,我定义了他的初始值为2,因为我希望得到的是倒数10个数据里面的前面5个数据,可能看着有些别扭,读者可以自己试一试,就明白其中的差距了,之后采用list.addAll()方法,希望可以将刚查到的数据累加到原来的List中,而且我们希望新增加的数据是在原来list的上面,而不是下面,所以最好使用list.addAll(0.mData);

其实很多时候我们需要控制ListView,让它显示最新的数据,但是PullToRefreshListView没有setSelection()这个方法,但其实还是可以实现的,需要转个弯,代码如下:

/**
	 * @Description 滑动到列表底部
	 */
	private void scrollToBottomListItem() {
		ListView lv = mlistview.getRefreshableView();
		if (lv != null) {
			lv.setSelection(mAdapter.getCount() + 1);

		}
	}

通过上面的代码可以实现Listview显示在最底部,需要加在什么地方就看自己的需要了


三 自定义button按钮播放语音

这个自定义播放语音的botton是参考别人的,在文章的开头就已经提及,这里就不贴代码了,原作者播放语音的时候是有bug的,就是播放完语音之后,动画效果完成后会变成一个方块,这里做出改进。

/**
		 * 点击按钮语音发出
		 */
		button.setAudioFinishRecorderListener(new AudioFinishRecorderListener() {

			@Override
			public void onFinished(float seconds, String filePath) {

				RecorderUtil recorder = new RecorderUtil(1, seconds, filePath);
				mDatas.add(recorder);
				mAdapter.notifyDataSetChanged();
				scrollToBottomListItem();
				if (new ComeModle(MainActivity.this).save(1, seconds, filePath)) {
//					Toast.makeText(MainActivity.this, "save success!!!", Toast.LENGTH_SHORT).show();
					Log.d(TAG, "save OK");
				} else {
					Log.d(TAG, "save Failed");
//					Toast.makeText(MainActivity.this, "save failed!", Toast.LENGTH_SHORT).show();
				}
			}
		});

		mAdapter = new RecorderBaseAdapter(this, mDatas);
		mlistview.setAdapter(mAdapter);
		/**
		 * 列表点击播放
		 */
		mlistview.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				// 播放动画
				if (viewanim != null) {// 让第二个播放的时候第一个停止播放
					viewanim.setBackgroundResource(R.drawable.adj);
					viewanim = null;
				}
				viewanim = view.findViewById(R.id.id_recorder_anim);
				viewanim.setBackgroundResource(R.drawable.play);
				AnimationDrawable drawable = (AnimationDrawable) viewanim.getBackground();
				drawable.start();

				// 播放音频
				MediaManager.playSound(mDatas.get(position - 1).filePathString, new MediaPlayer.OnCompletionListener() {

					@Override
					public void onCompletion(MediaPlayer mp) {
						viewanim.setBackgroundResource(R.drawable.adj);
					}
				});
			}
		});

思路是原作者给的,但我加了很多新的东西,其中RecoderUtil中我加了类型,用于实现后面一左一右的功能,数据库数据保存以及点击按钮语音播放之后会显示最新的语音数据,之后MediaManager中改变position的位子,不修改会造成数组越界,改变View中setBackgroundResourse()中的id值,这样播放动画效果后不会出现崩溃。

这个给一下有关播放MediaManager的源码:

package com.yeezone.cluster;


import java.io.IOException;

import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
/**
 * @Description 播放语音
 * @author xu.chen
 * @datetime 2016/3/24
 */
public class MediaManager {


	private static MediaPlayer mPlayer;
	
	private static boolean isPause;

	public static  void playSound(String filePathString,
			OnCompletionListener onCompletionListener) {
		// TODO Auto-generated method stub
		if (mPlayer==null) {
			mPlayer=new MediaPlayer();
			//保险起见,设置报错监听
			mPlayer.setOnErrorListener(new OnErrorListener() {
				
				@Override
				public boolean onError(MediaPlayer mp, int what, int extra) {
					// TODO Auto-generated method stub
					mPlayer.reset();
					return false;
				}
			});
		}else {
			mPlayer.reset();//就回复
		}
		
		try {
			mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
			mPlayer.setOnCompletionListener(onCompletionListener);
			mPlayer.setDataSource(filePathString);
			mPlayer.prepare();
			mPlayer.start();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 停止函数
	 */
	public static void pause(){
		if (mPlayer!=null&&mPlayer.isPlaying()) {
			mPlayer.pause();
			isPause=true;
		}
	}
	
	/**
	 * 继续
	 */
	public static void resume()
	{
		if (mPlayer!=null&&isPause) {
			mPlayer.start();
			isPause=false;
		}
	}
	

	public  static void release()
	{
		if (mPlayer!=null) {
			mPlayer.release();
			mPlayer=null;
		}
	}
}

四 Listview界面

这边也可以参考我之前写的代码,网址 

聊天LIstView  


都知道时间越长,语音的长度也会越长,这里讲一下如何确定语音的长度

首先定义确定系统高度

// 获取系统宽度
		WindowManager wManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics outMetrics = new DisplayMetrics();
		wManager.getDefaultDisplay().getMetrics(outMetrics);
		mMaxItemWith = (int) (outMetrics.widthPixels * 0.7f);
		mMinItemWith = (int) (outMetrics.widthPixels * 0.15f);

之后返回界面的时候需要做一些处理,代码如下:

holder.seconds.setText(Math.round(mData.get(position).time) + "\"");
ViewGroup.LayoutParams lParams = holder.length.getLayoutParams();
lParams.width = (int) (mMinItemWith + mMaxItemWith / 60f * mData.get(position).time);
holder.length.setLayoutParams(lParams);

通过这样,就可以实现长度的自由变化。

源码地址,说一下,Listview需要自己关联一下,上面有讲,不然会报错

http://download.csdn.net/detail/qq_31307919/9492124

下面为效果图






 


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要实现Android仿微信语音通话的效果,你可以按照以下步骤进行操作: 1. 首先,在styles.xml文件中定义一个自定义的对话框主题,可以参考引用\[1\]中的代码。这个主题可以设置对话框的背景透明、无边框、浮现在activity之上以及背景模糊显示等效果。 2. 在strings.xml文件中定义三个字符串资源,分别表示正常录音状态、录音中状态和取消发送状态。可以参考引用\[2\]中的代码。 3. 在布局文件中创建一个用于显示语音通话的界面,可以使用一个ImageView显示语音图标,一个TextView显示录音状态,以及一个Button用于开始和结束录音。 4. 在Activity中,根据用户的操作来改变TextView的文本内容,以及根据录音状态来改变ImageView的图标。 5. 使用MediaRecorder类来实现录音功能,可以在Button的点击事件中开始和结束录音。 6. 使用AudioManager类来控制音频的播放和停止,可以在Activity的生命周期方法中进行相应的操作。 通过以上步骤,你可以实现一个仿微信语音通话的效果。记得根据你的具体需求进行适当的修改和调整。 #### 引用[.reference_title] - *1* *2* [Android 仿微信实现语音聊天功能](https://blog.csdn.net/lhk147852369/article/details/78658055)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值