用javascript在码实云平台上,可以在云里编写原生的移动应用。移动应用有时需要像微信那样用手机录音,把语音上传到云存储里,并且在应用里可以点击播放。这个功能码实平台提供了全套的实现,而实现的方式和手机的相机调用非常相似,也是把语音当做一个多媒体附件来处理。因此,如果你先熟悉下相机拍照那个教程的代码,对理解本应用实例会有很大的帮助。
本实例的代码里,有较多部分是用于录音播放的UI和控制。createRow函数比其他数据相关的教程里略长,Mash5.Tenant.File.SoundPlayer.create是码实平台SDK创建音频播放器的调用。事先用Mash5.Tenant.File.download从云存储里获取音频录音文件。代码里把页面的右上角按钮定制为加号的发布按钮,按钮的事件处理调用了Mash5.Tenant.File.uploadFromRecorder来录制语音。
Class.create(Mash5.Widget, {
playImage: undefined,
stopImage: undefined,
initialize : function () {
var context = this.getContext();
//获取播发图标
context.getResource({
id: "540920870cf2720cf9aa3fac",
callback: function(file) {
this.playImage = file;
}.bind(this)
});
//获取停止图标
context.getResource({
id: "540920870cf2720cf9aa3fae",
callback: function(file) {
this.stopImage = file;
}.bind(this)
});
//设置导航条右按钮为创建功能
this.getCurrentPage().setRightNavButton({
style: Mash5.UI.NavigationButtonStyle.ADD,
listener: function () {
//创建参数
var parameters = this.createAddParameters();
Mash5.Tenant.File.uploadFromRecorder({
context: context,
onprogresschanged: parameters.onprogresschanged,//上传进度回调
setCancelListener: parameters.setCancelListener//设置取消的回调
},
parameters.onload);
}.bind(this),
});
this.render();
},
render: function() {
var context = this.getContext();
var container = Ti.UI.createView({
width: Ti.UI.FILL,
height: Ti.UI.FILL,
layout:'vertical'
});
this.setContentView(container);
var tipLabel = Ti.UI.createLabel({
width: Ti.UI.FILL,
height: Ti.UI.FILL,
font: {
fontSize: '16dip',
fontFamily: 'Helvetica Neue'
},
color: '#404040',
textAlign: 'center',
text: '正在获取数据...'
});
container.add(tipLabel);
//查询数据
var params = {
'method.name': 'mash5.task.queryFeeds',
'method.version': 'Titanium',
'method.optimize': 'fetchOne',
'method.optimize.includeField.fieldName': '$format$' + JSON.stringify(['_id', 'name', 'Positions']),
'page.nextTime': '9999999999999',
'page.perPageSize': 1000,
'query.bo.nameSpace': 'dev.bo.basic.luyinjiaocheng_1409883815008'
};
Mash5.Network.executeHTTPClientForAllResult(context, params, function (result) {
var feeds = result.object && result.object.nextData;
if (feeds.length > 0) {
//查询到录音
//去掉提示的View
container.remove(tipLabel);
//显示所有录音
var tableView = Ti.UI.createTableView({
width : Ti.UI.FILL,
height : Ti.UI.FILL
});
container.add(tableView);
var rows = [];
for (var i = 0, len = feeds.length; i < len; i++) {
var row = this.createRow(feeds[i]);
rows.push(row);
}
tableView.setData(rows);
} else {
tipLabel.text = '没有数据';
}
}.bind(this));
},
createAddParameters: function() {
var progressDialog = Mash5.UI.createProgressDialog();
progressDialog.setProgress(0, "正在上传录音...");
return {
onprogresschanged: function(progress) {
progressDialog.show();
progressDialog.setProgress(progress, "正在上传录音...")
},
setCancelListener: function(listener) {
progressDialog.setCancelListener(listener)
},
onload: function(r) {
progressDialog.hide();
setTimeout(function() {
progressDialog.hide()
},
600);
if (r.success) {
var fileInfo = r.fileInfo;
this.addFeed(fileInfo);
} else {
alert(r.message);
}
}.bind(this)
}
},
addFeed: function(fileInfo) {
var context = this.getContext();
// 获取数据格式模板
context.getBO({
nameSpace: 'dev.bo.basic.luyinjiaocheng_1409883815008',
callback: function (bo) {
if(bo) {
bo.Fields[0].Value = fileInfo;
// 发布数据
var params = {
'method.name' : 'mash5.task.addFeed',
'method.version' : 'Titanium"',
'method.optimize' : 'fetchOne',
'method.optimize.includeField.fieldName' : '$format$' + JSON.stringify(['_id', 'name', 'Positions']),
'insert.appId' : context.getCurrentAppId(),
'insert.bo' : JSON.stringify(bo)
};
Mash5.Network.executeHTTPClientForAllResult(context, params, function (result) {
if (!result.success || !result.object) {
alert('发布信息失败。');
return;
}
this.render();
}.bind(this));
}
}.bind(this)
});
},
//显示一个录音文件
createRow: function (feed) {
var context = this.getContext();
// 录音文件信息
var fileInfo = feed.bo.Fields[0].Value;
var row = Ti.UI.createTableViewRow({
width: '100%',
height: Ti.UI.SIZE,
selectionStyle : 0,
});
var container = Ti.UI.createView({
width: Ti.UI.FILL,
height: '60dip'
});
row.add(container);
var horizontal = Ti.UI.createView({
width: '90dip',
height: '40dip',
top: '10dip',
left: '20dip',
borderRadius: '5dip',
borderWidth: '1.5dip',
borderColor: '#c8d3d6'
});
// 播放按钮
var playAndStopBtn = Ti.UI.createImageView({
width: '30dip',
height: '30dip',
top: '5dip',
left: '5dip',
bubbleParent: false,
canScale: false
});
if (!this.playImage) {
context.getResource({
id: "540920870cf2720cf9aa3fac",
callback: function(file) {
this.playImage = file;
playAndStopBtn.setImage(this.playImage);
}.bind(this)
});
} else {
playAndStopBtn.setImage(this.playImage);
}
horizontal.add(playAndStopBtn);
// 时间显示
var timeLabel = Ti.UI.createLabel({
width: Ti.UI.SIZE,
height: '30dip',
font: {fontSize: '14dip'},
color: '#000',
top: '5dip',
left: '40dip',
text: '00:00'
});
var duration = fileInfo.milliSecond ? fileInfo.milliSecond: 0;
timeLabel.setText(this.durationToString(duration));
horizontal.add(timeLabel);
var isPlay = false,
player,
timer;
//播放按钮点击事件
container.addEventListener('click', function () {
var context = this.getContext();
if (!isPlay) {
isPlay = true;
// 调用SDK下载音频文件
Mash5.Tenant.File.download({
context: context,
fileInfo: fileInfo,
onprogresschanged: function(progress) {
//下载进度的事件progress是进度,取值范围ie0-1。
if (!Mash5.UI.activityIndicator.isShow()) {
Mash5.UI.activityIndicator.showModal('正在下载录音文件...');
}
Mash5.UI.activityIndicator.setMessage(Mash5.string.get('正在下载录音文件...') + Math.floor(progress * 100) + '%');
}
}, function(r) {
Mash5.UI.activityIndicator.hideModal();
if (r.success) {
//调用SDK的音频播放创建播放对象。
player = Mash5.Tenant.File.SoundPlayer.create(r.file);
if (player) {
//计时器,显示播放进度。
timer = setInterval(function () {
duration -= 1000;
if (duration < 0) {
duration = 0;
}
timeLabel.setText(this.durationToString(duration));
}.bind(this), 1000);
//播放按钮变成停止
if (!this.stopImage) {
context.getResource({
id: "540920870cf2720cf9aa3fae",
callback: function(file) {
this.stopImage = file;
playAndStopBtn.setImage(this.stopImage);
}.bind(this)
});
} else {
playAndStopBtn.setImage(this.stopImage);
}
// 调用播放方法
player.play();
// 播放完的事件处理
player.addEventListener('complete', function () {
clearInterval(timer);
timer = null;
//播放完清理播放对象
player.release();
player = null;
//播放完,按钮恢复播放的样式
if (!this.playImage) {
context.getResource({
id: "540920870cf2720cf9aa3fac",
callback: function(file) {
this.playImage = file;
playAndStopBtn.setImage(this.playImage);
}.bind(this)
});
} else { playAndStopBtn.setImage(this.playImage);
}
duration = fileInfo.milliSecond ? fileInfo.milliSecond: 0;
timeLabel.setText(this.durationToString(duration));
isPlay = false;
}.bind(this));
}
}
}.bind(this));
} else {
if (!player) return;
//调用停止播放的方法
player.stop();
//清理播放对象
player.release();
player = null;
if (timer) {
clearInterval(timer);
timer = null;
}
if (!this.playImage) {
context.getResource({
id: "540920870cf2720cf9aa3fac",
callback: function(file) {
this.playImage = file;
playAndStopBtn.setImage(this.playImage);
}.bind(this)
});
} else {
playAndStopBtn.setImage(this.playImage);
}
duration = fileInfo.milliSecond ? fileInfo.milliSecond: 0;
timeLabel.setText(this.durationToString(duration));
isPlay = false;
}
}.bind(this));
container.add(horizontal);
return row;
},
//毫秒数转成"分钟:秒"的格式的文本
durationToString: function(duration) {
if (duration) {
var minutes,
seconds;
if (duration >= 60000) {
minutes = Math.floor(duration / 60000);
if (minutes <= 9) {
minutes = '0' + minutes.toString();
}
} else {
minutes = '00';
}
seconds = Math.floor(duration / 1000) % 60;
if (seconds <= 9) {
seconds = '0' + seconds.toString();
}
return minutes.toString() + ':' + seconds.toString();
} else {
return '00:00';
}
}
})