2017-11-22 12:07:43 qq_24343389 阅读数 545
  • 微信开发群发多图文消息-微信开发16(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 右侧可办理会员卡。微信群发多图文消息开发是子恒老师《子恒说微信开发》视频教程的第16部。详细讲解了用php开发微信群发图文消息。内容包含图文消息前端页面,一个页面插入多个百度UEditor,群发多图文,查询和删除图文消息等等。欢迎反馈,微信号:QQ68183131

    8089 人正在学习 去看看 秦子恒

1、登录微信公众号 开发 -接口权限



2、开通接收语音识别结果权限



3、点击确定



2016-06-13 09:10:06 soul_code 阅读数 4756
  • 微信开发群发多图文消息-微信开发16(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 右侧可办理会员卡。微信群发多图文消息开发是子恒老师《子恒说微信开发》视频教程的第16部。详细讲解了用php开发微信群发图文消息。内容包含图文消息前端页面,一个页面插入多个百度UEditor,群发多图文,查询和删除图文消息等等。欢迎反馈,微信号:QQ68183131

    8089 人正在学习 去看看 秦子恒

-环境、框架
1、服务器:tomcat8.0.32
2、后台框架:jfinal2.2
3、数据库:无
4、前端:wechat JS SDK
5、第三方jar:wechat4j、sauronsoftware
一、引入wechat JS SDK
这一步比较简单,按照微信给的开发文档一步一步配置就就行,但是步骤比较繁多,利用第三方依赖库wechat4j,只需几行代码即可实现JS JDK的导入。
1、首先是后台Action

public void authWeJs() {
        String url = getPara("url", null);
        long timestamp = System.currentTimeMillis() / 1000;
        String nonceStr = UUID.randomUUID().toString();
        String ticket = TokenProxy.jsApiTicket();
        String token = TokenProxy.accessToken();
        String appid = Config.instance().getAppid();
        String sortStr = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr
                + "&timestamp=" + timestamp + "&url=" + url;
        String signature = DigestUtils.sha1Hex(sortStr);
        setAttr("timestamp", timestamp);
        setAttr("signature", signature);
        setAttr("token", token);
        setAttr("appid", appid);
        setAttr("nonceStr", nonceStr);
        System.out.println(signature);
        System.out.println(sortStr);
        System.out.println(ticket);
        renderJson();
    }

2、前端JS请求Action获取接入SDK所需的appid、timestamp、nonceStr、signature

wx.config({
                debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                appId: json.appid, // 必填,公众号的唯一标识
                timestamp:json.timestamp , // 必填,生成签名的时间戳
                nonceStr: json.nonceStr, // 必填,生成签名的随机串
                signature:json.signature,// 必填,签名,见附录1
                jsApiList: [
                            'checkJsApi',
                            'onMenuShareTimeline',
                            'onMenuShareAppMessage',
                            'onMenuShareQQ',
                            'onMenuShareWeibo',
                            'hideMenuItems',
                            'showMenuItems',
                            'hideAllNonBaseMenuItem',
                            'showAllNonBaseMenuItem',
                            'translateVoice',
                            'startRecord',
                            'stopRecord',
                            'onRecordEnd',
                            'playVoice',
                            'pauseVoice',
                            'stopVoice',
                            'uploadVoice',
                            'downloadVoice',
                            'chooseImage',
                            'previewImage',
                            'uploadImage',
                            'downloadImage',
                            'getNetworkType',
                            'openLocation',
                            'getLocation',
                            'hideOptionMenu',
                            'showOptionMenu',
                            'closeWindow',
                            'scanQRCode',
                            'chooseWXPay',
                            'openProductSpecificView',
                            'addCard',
                            'chooseCard',
                            'openCard'   
                ] // 必填,需要使用的JS接口列表,所有JS接口
            });

三、录制语言

// 1、开始录制
wx.startRecord(); 
//2、停止录制
wx.stopRecord({
    success: function (res) {
        var localId = res.localId;
    }
});
//3、上传录制好的音频文件,注意这里是上传的微信服务器,有效期只有三天,到目前位置一直都是使用的微信SDK的API,接下来我们需要上传到自己的服务器
wx.uploadVoice({
    localId: '', // 需要上传的音频的本地ID,由stopRecord接口获得
    isShowProgressTips: 1, // 默认为1,显示进度提示
        success: function (res) {
        var serverId = res.serverId; // 返回音频的服务器端ID
    }
});
// 4、然而JS JDK文档里面并没有告知如何下载多媒体资源(微信文档的坑),不过没有关系第三方依赖库wechat4j提供了获取持久化素材的方案,几行代码就可以将多媒体资源上传到自己服务器,引入wechat4j,只需两行代码
    MediaFile mediaFile = new MediaFile();
    byte[] download = mediaFile.download(media_id);
//media_id 就是第三步骤中的serverId
// 讲byte转为file
public static void byte2File(byte[] buf, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            if (!dir.exists() && dir.isDirectory()) {
                dir.mkdirs();
            }
            file = new File(filePath + File.separator + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(buf);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
// 第二个坑来了,从微信服务器下载的音频文件是amr格式,然而html的audio标签并不支持amr的播放,这里我们需要用到第二个三方依赖库sauronsoftware把amr转为MP3格式
public static void changeToMp3(String sourcePath, String targetPath) {
        File source = new File(sourcePath);
        File target = new File(targetPath);
        AudioAttributes audio = new AudioAttributes();
        Encoder encoder = new Encoder();
        audio.setCodec("libmp3lame");
        EncodingAttributes attrs = new EncodingAttributes();
        attrs.setFormat("mp3");
        attrs.setAudioAttributes(audio);
        try {
            encoder.encode(source, target, attrs);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InputFormatException e) {
            e.printStackTrace();
        } catch (EncoderException e) {
            e.printStackTrace();
        }
    }

至此,微信语言开发的流程基本结束,前端返回语音路径用audio标签播发即可
sauronsoftware.jar下载
wechat4j.jar

2015-08-26 13:06:22 oldinaction 阅读数 6920
  • 微信开发群发多图文消息-微信开发16(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 右侧可办理会员卡。微信群发多图文消息开发是子恒老师《子恒说微信开发》视频教程的第16部。详细讲解了用php开发微信群发图文消息。内容包含图文消息前端页面,一个页面插入多个百度UEditor,群发多图文,查询和删除图文消息等等。欢迎反馈,微信号:QQ68183131

    8089 人正在学习 去看看 秦子恒

当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。服务器在解析此数据包,获取相关参数的值从而做出回复。接收普通消息主要包括:文本消息、图片消息、语音消息、视频消息、小视频消息、地理位置消息、链接消息。XML数据包结构和相关参数如下:

1、文本消息

 <xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName> 
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[this is a test]]></Content>
 <MsgId>1234567890123456</MsgId>
 </xml>
参数				描述
ToUserName		开发者微信号
FromUserName	 发送方帐号(一个OpenID)
CreateTime	 	消息创建时间 (整型)
MsgType	 		text
Content	 		文本消息内容
MsgId	 		消息id,64位整型

那么这些参数该如何获取呢,示例代码如下:

index.php(完整代码下载

<?php
/**
  * 作者:smalle
  * 网址:http://blog.csdn.net/oldinaction
  * 微信公众号:smallelife
  */

//定义 token
define("TOKEN", "smalle");
//实例化对象
$wechatObj = new wechatCallbackapiTest();
//调用函数
if (isset($_GET['echostr'])) {
	$wechatObj->valid();
}else{
	$wechatObj->responseMsg();
}

class wechatCallbackapiTest
{
	public function valid()
	{
		$echoStr = $_GET["echostr"];
		if($this->checkSignature()){
			echo $echoStr;
			exit;
		}
	}

	public function responseMsg()
	{
		$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];  

		if (!empty($postStr)){  
			libxml_disable_entity_loader(true);//安全防护  
			$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);  
			$fromUsername = $postObj->FromUserName;  
			$toUsername = $postObj->ToUserName;
			$createTime = $postObj->CreateTime;
			$msgType = $postObj->MsgType;
			$content = $postObj->Content;
			$msgId = $postObj->MsgId;
			if($msgType == 'text'){
				$textTpl = "<xml>  
						<ToUserName><![CDATA[%s]]></ToUserName>  
						<FromUserName><![CDATA[%s]]></FromUserName>  
						<CreateTime>%s</CreateTime>  
						<MsgType><![CDATA[text]]></MsgType>  
						<Content><![CDATA[%s]]></Content>  
						<FuncFlag>0</FuncFlag>  
						</xml>";
				$time = time();
				$contentStr = "您发的是消息包含以下信息:\n发信人OpenID:".$fromUsername."\n收信人微信号:".$toUsername."\n发信时间:".$createTime."\n消息类型:".$msgType."\n消息内容:".$content."\n消息ID:".$msgId;  
				$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $contentStr);  
				echo $resultStr;  
			}else{
				$textTpl = "<xml>  
						<ToUserName><![CDATA[%s]]></ToUserName>  
						<FromUserName><![CDATA[%s]]></FromUserName>  
						<CreateTime>%s</CreateTime>  
						<MsgType><![CDATA[text]]></MsgType>  
						<Content><![CDATA[%s]]></Content>  
						<FuncFlag>0</FuncFlag>  
						</xml>";
				$time = time();
				$contentStr = "您发的消息类型不是文本。而是".$msgType;
				$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $contentStr);  
				echo $resultStr;  
			}

		}
	}
		
	private function checkSignature()
	{
		if (!defined("TOKEN")) {
			throw new Exception('TOKEN is not defined!');
		}
		$signature = $_GET["signature"];
		$timestamp = $_GET["timestamp"];
		$nonce = $_GET["nonce"];
		$token = TOKEN;
		$tmpArr = array($token, $timestamp, $nonce);
		sort($tmpArr, SORT_STRING);
		$tmpStr = implode( $tmpArr );
		$tmpStr = sha1( $tmpStr );
		
		if( $tmpStr == $signature ){
			return true;
		}else{
			return false;
		}
	}
}

?>
效果预览:


代码分析:

  • 第32-42行【$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];......$msgId = $postObj->MsgId;】:实现获取用户发送过来的消息数据。
  • 第43-55行【if($msgType == 'text'){......echo $resultStr;】:实现的是被动回复文本消息给用户

2、图片消息

使用方法同文本消息,此处不再赘述,不懂得话可以在博文后面留言。

 <xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[image]]></MsgType>
 <PicUrl><![CDATA[http://blog.csdn.net/oldinaction]]></PicUrl>
 <MediaId><![CDATA[media_id]]></MediaId>
 <MsgId>1234567890123456</MsgId>
 </xml>
参数				描述
ToUserName		开发者微信号
FromUserName	发送方帐号(一个OpenID)
CreateTime		消息创建时间 (整型)
MsgType	 		image
PicUrl	 		图片链接
MediaId	 		图片消息媒体id,可以调用多媒体文件下载接口拉取数据。
MsgId	 		消息id,64位整型

3、语音消息

使用方法同文本消息,此处不再赘述,不懂得话可以在博文后面留言。

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<Format><![CDATA[Format]]></Format>
<MsgId>1234567890123456</MsgId>
</xml>
参数				描述
ToUserName		开发者微信号
FromUserName	发送方帐号(一个OpenID)
CreateTime		消息创建时间 (整型)
MsgType	 		语音为voice
MediaId	 		语音消息媒体id,可以调用多媒体文件下载接口拉取数据。
Format	 		语音格式,如amr,speex等
MsgID	 		消息id,64位整型

请注意,开通语音识别后,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,增加一个Recongnition字段(注:由于客户端缓存,开发者开启或者关闭语音识别功能,对新关注者立刻生效,对已关注用户需要24小时生效。开发者可以重新关注此帐号进行测试)。开启语音识别后的语音XML数据包如下:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<Format><![CDATA[Format]]></Format>
<Recognition><![CDATA[腾讯微信团队]]></Recognition>
<MsgId>1234567890123456</MsgId>
</xml>
多出的字段中,Format为语音格式,一般为amr,Recognition为语音识别结果,使用UTF8编码。

4、视频消息

使用方法同文本消息,此处不再赘述,不懂得话可以在博文后面留言。

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
参数				描述
ToUserName		开发者微信号
FromUserName	发送方帐号(一个OpenID)
CreateTime		消息创建时间 (整型)
MsgType	 		视频为video
MediaId	 		视频消息媒体id,可以调用多媒体文件下载接口拉取数据。
ThumbMediaId		视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。
MsgId	 		消息id,64位整型

5、小视频消息

使用方法同文本消息,此处不再赘述,不懂得话可以在博文后面留言。

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[shortvideo]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
参数				描述
ToUserName		开发者微信号
FromUserName	发送方帐号(一个OpenID)
CreateTime		消息创建时间 (整型)
MsgType	 		小视频为shortvideo
MediaId	 		视频消息媒体id,可以调用多媒体文件下载接口拉取数据。
ThumbMediaId		视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。
MsgId	 		消息id,64位整型

6、地理位置消息

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType><![CDATA[location]]></MsgType>
<Location_X>23.134521</Location_X>
<Location_Y>113.358803</Location_Y>
<Scale>20</Scale>
<Label><![CDATA[位置信息]]></Label>
<MsgId>1234567890123456</MsgId>
</xml> 
参数				描述
ToUserName		开发者微信号
FromUserName	发送方帐号(一个OpenID)
CreateTime		消息创建时间 (整型)
MsgType	 		location
Location_X		地理位置维度
Location_Y		地理位置经度
Scale	 		地图缩放大小
Label	 		地理位置信息
MsgId	 		消息id,64位整型

当用户给公众账号发送位置时,便可以获取相应的地理位置信息。部分示例代码如下:

index.php(完整代码下载

$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];  

if (!empty($postStr)){  
	libxml_disable_entity_loader(true);//安全防护  
	$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);  
	$fromUsername = $postObj->FromUserName;  
	$toUsername = $postObj->ToUserName;
	$msgType = $postObj->MsgType;
	$j = $postObj->Location_Y;//经度
	$w = $postObj->Location_X;//纬度
	$label = $postObj->Label;//地理位置信息
	if($msgType == 'location'){
		$textTpl = "<xml>  
				<ToUserName><![CDATA[%s]]></ToUserName>  
				<FromUserName><![CDATA[%s]]></FromUserName>  
				<CreateTime>%s</CreateTime>  
				<MsgType><![CDATA[text]]></MsgType>  
				<Content><![CDATA[%s]]></Content>  
				<FuncFlag>0</FuncFlag>  
				</xml>";
		$time = time();
		$contentStr = "您的位置信息如下:\n经度:".$j."\n纬度:".$w."\n地理位置信息:".$label;
		$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $contentStr);  
		echo $resultStr;  
	}else{
		echo '';
	}

}
效果展示:

现在你可能觉得这一小串数字没什么用,到后面我会分享一些关于位置信息的小案例,那个时候就起作用了。


7、链接消息

使用方法同文本消息,此处不再赘述,不懂得话可以在博文后面留言。

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType><![CDATA[link]]></MsgType>
<Title><![CDATA[公众平台官网链接]]></Title>
<Description><![CDATA[公众平台官网链接]]></Description>
<Url><![CDATA[url]]></Url>
<MsgId>1234567890123456</MsgId>
</xml>
参数				描述
ToUserName		接收方微信号
FromUserName	发送方微信号,若为普通用户,则是一个OpenID
CreateTime		消息创建时间
MsgType	 		消息类型,link
Title	 			消息标题
Description		消息描述
Url	 			消息链接
MsgId	 		消息id,64位整型




===================================微笑微笑微笑===================================

关注【Smalle】【微信公众号:smallelife】              微笑             捐赠【Smalle】【微信公众号:smallelife】

关注就有豪礼相送哦,羡慕源码、羡慕工具、羡慕文档应有尽有      微笑       你的扫码便是我前进的动力,羡慕扫码、羡慕扫码、羡慕扫码

===================================微笑微笑微笑===================================

                                     


2015-09-15 10:32:39 ROVAST 阅读数 1918
  • 微信开发群发多图文消息-微信开发16(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 右侧可办理会员卡。微信群发多图文消息开发是子恒老师《子恒说微信开发》视频教程的第16部。详细讲解了用php开发微信群发图文消息。内容包含图文消息前端页面,一个页面插入多个百度UEditor,群发多图文,查询和删除图文消息等等。欢迎反馈,微信号:QQ68183131

    8089 人正在学习 去看看 秦子恒

在做微信语音识别时,需要将用户的聊天和语音记录存储到数据库中

</pre><pre name="code" class="php">        $openid = trim($object->FromUserName);
        $media_id = trim($object->MediaId);
        $create_time = trim($object->CreateTime);
        $voice_text = trim($object->Recognition);

        $data                = array();
        $data['user_id']     = D('User')->getUseridByOpenid($openid);
        $data['voice']       = D('Weixin')->saveMedia($media_id);
        $data['voice_text']  = $voice_text ? $voice_text:'1';
        $data['status']      = 0;
        $data['create_time'] = $create_time ? $create_time : 222;
        $data['update_time'] = time();

        $rs = M('Voice')->add($data);


请将受到的数据进行trim处理,不然你就等着哭吧,不多说了,都是泪

2015-11-02 20:08:37 Jaden_hool 阅读数 3500
  • 微信开发群发多图文消息-微信开发16(PHP)

    会员免费看,http://edu.csdn.net/lecturer/842 右侧可办理会员卡。微信群发多图文消息开发是子恒老师《子恒说微信开发》视频教程的第16部。详细讲解了用php开发微信群发图文消息。内容包含图文消息前端页面,一个页面插入多个百度UEditor,群发多图文,查询和删除图文消息等等。欢迎反馈,微信号:QQ68183131

    8089 人正在学习 去看看 秦子恒

代码是从聊天类项目中抽出来的,播放类中含有本地播放和网络播放,做法仿微信,先将网络路径中的.amr文件下载下来,然后存到本地播放。
一、录音类

import java.io.File;
import java.io.IOException;

import android.media.MediaRecorder;

public class ChatRecorder {

    private String mOutputFileName = "";
    private MediaRecorder mRecorder = null;
    private long mStartTime = 0L;
    private static ChatRecorder mChatRecorder = null;

    private ChatRecorder() {}

    public static ChatRecorder getInstance() {
        if (mChatRecorder == null) {
            synchronized (ChatRecorder.class) {
                if (mChatRecorder == null) {
                    mChatRecorder = new ChatRecorder();
                }
            }
        }
        return mChatRecorder;
    }

    public void initRecorder() {
        mRecorder = new MediaRecorder();
    }

    public void startRecord(String outputFileName) {
        if (mRecorder == null) {
            return;
        }
        this.mOutputFileName = outputFileName;
        File parentFile = new File(outputFileName).getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
        mRecorder.setOutputFile(mOutputFileName);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        try {
            mRecorder.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
        mRecorder.start();
        mStartTime = System.currentTimeMillis();
    }


    public long stopRecord() {
        if (mRecorder != null) {
            mRecorder.stop();
            return System.currentTimeMillis() - mStartTime;
        }
        return 0L;
    }

    public void exitRecorder() {
        if (mRecorder != null) {
            mRecorder.release();
            mRecorder = null;
        }
    }

    public String getOutputFileName() {
        return mOutputFileName;
    }

    public double getAmplitude() {
        if (mRecorder != null) {
            return (mRecorder.getMaxAmplitude() / 2700.0);
        } else {
            return 0;
        }
    }
}

二、播放类

package net.bangbao.im.imkit.base;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

import net.bangbao.R;
import net.bangbao.XConfig;
import net.bangbao.XManager;
import net.bangbao.utils.EncryptionUtils;
import net.bangbao.utils.FileUtil;
import net.bangbao.utils.UIUtils;
import net.bangbao.utils.Utils;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.net.Uri;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;

public class ChatPlayer {
    private static final String TAG = ChatPlayer.class.getSimpleName();
    private static final int MSG_WHAT_PLAY = 1000;
    private static ChatPlayer mChatPlayer = null;
    private MediaPlayer mPlayer = null;
    private String mCurrentUrl = "";
    private OnMediaPlayListener mMediaPlayListener = null;
    private Handler mHandler = null;
    Callback downloadCallback = new Callback() {

        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what == MSG_WHAT_PLAY) {
                if (msg.obj instanceof File) {
                    File localFile = (File) msg.obj;
                    playFromLocal(localFile);
                }
            }
            return false;
        }
    };

    private ChatPlayer() {}

    public static ChatPlayer getInstance() {
        if (mChatPlayer == null) {
            synchronized (ChatPlayer.class) {
                if (mChatPlayer == null) {
                    mChatPlayer = new ChatPlayer();
                }
            }
        }
        return mChatPlayer;
    }

    public interface OnMediaPlayListener {

        void onStart(String url);

        void onCompletion(String url);

        void onError(String url);
    }

    public void init() {
        mPlayer = new MediaPlayer();
        mHandler = new Handler(downloadCallback);
    }

    public void play(final String url, final OnMediaPlayListener listener) {
        if (mPlayer == null) {
            return;
        }
        if (mPlayer.isPlaying()) {
            mPlayer.stop();
            if (mMediaPlayListener != null) {
                mMediaPlayListener.onCompletion(mCurrentUrl);
            }
        }
        mCurrentUrl = url;
        mMediaPlayListener = listener;
        mPlayer.setOnCompletionListener(new OnCompletionListener() {

            @Override
            public void onCompletion(MediaPlayer mp) {
                if (mMediaPlayListener != null) {
                    mMediaPlayListener.onCompletion(mCurrentUrl);
                }
            }
        });

        mPlayer.setOnErrorListener(new OnErrorListener() {

            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                if (mMediaPlayListener != null) {
                    listener.onError(mCurrentUrl);
                }
                return false;
            }
        });

        if (!FileUtil.isCanUseSDCard()) {
            UIUtils.toastMsgFromResource(XManager.getManager().getApplication(), R.string.sdcard_err);
            return;
        }

        String wholeUrl = Utils.getWholeUrl(mCurrentUrl, XConfig.FILE_SCHEME);
        if (wholeUrl.startsWith(XConfig.FILE_SCHEME)) {
            playFromLocal(wholeUrl);
            return;
        }

        File localDir = new File(XConfig.DIR_CHAT_VOICE_CACHE);
        if (!localDir.exists()) {
            localDir.mkdirs();
        }
        final File localFile = new File(localDir, mCurrentUrl + ".amr");
        if (localFile.exists()) {
            playFromLocal(localFile);
        } else {
            playFromNetwork(mCurrentUrl, localFile);
        }
    }

    public boolean isPlaying() {
        if (mPlayer == null) {
            return false;
        }
        return mPlayer.isPlaying();
    }

    public void stop() {
        if (mPlayer != null) {
            mPlayer.stop();
            if (mMediaPlayListener != null) {
                mMediaPlayListener.onCompletion(mCurrentUrl);
            }
        }
    }

    public void release() {
        if (mPlayer != null) {
            mPlayer.release();
            mPlayer = null;
            mHandler.removeMessages(MSG_WHAT_PLAY);
            if (mMediaPlayListener != null) {
                mMediaPlayListener.onCompletion(mCurrentUrl);
            }
        }
    }

    private void playFromNetwork(final String source, final File localFile) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                int count;
                try {
                    URL url = new URL(source);
                    URLConnection conn = url.openConnection();
                    conn.connect();

                    InputStream input = new BufferedInputStream(url.openStream());
                    OutputStream output = new FileOutputStream(localFile);

                    byte data[] = new byte[1024];

                    while ((count = input.read(data)) != -1) {
                        output.write(data, 0, count);
                    }
                    output.flush();
                    output.close();
                    input.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                Message msg = mHandler.obtainMessage();
                msg.what = MSG_WHAT_PLAY;
                msg.obj = localFile;
                mHandler.sendMessage(msg);

            }
        }).start();
    }

    private void playFromLocal(File localFile) {
        if (mPlayer == null) {
            return;
        }
        try {
            Uri uri = Uri.fromFile(localFile);
            mPlayer.reset();
            mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mPlayer.setDataSource(XManager.getManager().getApplication(), uri);
            mPlayer.prepare();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        mPlayer.start();
        if (mMediaPlayListener != null) {
            mMediaPlayListener.onStart(mCurrentUrl);
        }
    }

    private void playFromLocal(String localFilePath) {
        if (mPlayer == null) {
            return;
        }
        try {
            mPlayer.reset();
            mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mPlayer.setDataSource(localFilePath);
            mPlayer.prepare();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        mPlayer.start();
        if (mMediaPlayListener != null) {
            mMediaPlayListener.onStart(mCurrentUrl);
        }
    }
}
没有更多推荐了,返回首页