解决:编辑一条彩信,附件选择添加音频,返回到编辑界面选择play,不能播放,没有声音
【操作步骤】:编辑一条彩信,附件选择添加音频(外部音频),返回到编辑界面选择play,菜单键选择view slideshow
【测试结果】:不能播放,没有声音
【预期结果】:可以播放
根据以往的经验(之前也有一片博文涉及到类似的功能)这里首先想到的是乱码,通过查看数据库,也证实了这个想法;
因此,从文件管理器中共享一个中文文件名的音频文件(当然通过测试其他任何格式的文件包括图片,视频等只要是中文乱码则都有相同的问题)到短信中(文件管理器通过ACTION_SEND启动ComposeMessageActivity,该Activity在清单文件中注册了该Action);
CompseMessageActivity通过handleSendIntent()方法来接受Intent中的数据:
private boolean handleSendIntent() {
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras == null) {
return false;
}
final String mimeType = intent.getType();
String action = intent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
if (extras.containsKey(Intent.EXTRA_STREAM)) {
final Uri uri = (Uri)extras.getParcelable(Intent.EXTRA_STREAM);
getAsyncDialog().runAsync(new Runnable() {
@Override
public void run() {
mAttachFileUri = uri;
addAttachment(mimeType, uri, false);
}
}, null, R.string.adding_attachments_title);
return true;
} else if (extras.containsKey(Intent.EXTRA_TEXT)) {
mWorkingMessage.setText(extras.getString(Intent.EXTRA_TEXT));
return true;
}
} else if ((Intent.ACTION_SEND_MULTIPLE.equals(action) &&
extras.containsKey(Intent.EXTRA_STREAM)) || mIsSendMultiple) {
SlideshowModel slideShow = mWorkingMessage.getSlideshow();
final ArrayList<Parcelable> uris = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
if (uris.size() > 0) {
mIsSendMultiple = true;
}
int currentSlideCount = slideShow != null ? slideShow.size() : 0;
int importCount = uris.size();
if (importCount + currentSlideCount > SlideshowEditor.MAX_SLIDE_NUM) {
importCount = Math.min(SlideshowEditor.MAX_SLIDE_NUM - currentSlideCount,
importCount);
Toast.makeText(ComposeMessageActivity.this,
getString(R.string.too_many_attachments,
SlideshowEditor.MAX_SLIDE_NUM, importCount),
Toast.LENGTH_LONG).show();
}
// Attach all the pictures/videos asynchronously off of the UI thread.
// Show a progress dialog if adding all the slides hasn't finished
// within half a second.
final int numberToImport = importCount;
getAsyncDialog().runAsync(new Runnable() {
@Override
public void run() {
for (int i = 0; i < numberToImport; i++) {
Parcelable uri = uris.get(i);
addAttachment(mimeType, (Uri) uri, true);
}
updateMmsSizeIndicator();
}
}, null, R.string.adding_attachments_title);
return true;
}
return false;
}
调用addAttachment()方法;
private void addAttachment(String type, Uri uri, boolean append) {
if (uri != null) {
// When we're handling Intent.ACTION_SEND_MULTIPLE, the passed in items can be
// videos, and/or images, and/or some other unknown types we don't handle. When
// a single attachment is "shared" the type will specify an image or video. When
// there are multiple types, the type passed in is "*/*". In that case, we've got
// to look at the uri to figure out if it is an image or video.
boolean wildcard = "*/*".equals(type);
if (type.startsWith("image/")
|| (wildcard && uri.toString().startsWith(mImageUri))
|| (wildcard && isImageFile(uri))) {
addImage(uri, append);
} else if (type.startsWith("video/")
|| (wildcard && uri.toString().startsWith(mVideoUri))
|| (wildcard && isVideoFile(uri))) {
addVideo(uri, append);
} else if (type.startsWith("audio/")
|| (wildcard && uri.toString().startsWith(mAudioUri))
|| (wildcard && isAudioFile(uri))) {
addAudio(uri, append);
} else if (SystemProperties.getBoolean("persist.env.mms.vcard", true)
&& (type.equals("text/x-vcard")
|| (wildcard && isVcardFile(uri)))) {
addVcard(uri);
} else {
// Add prompt when file type is not image/video/audio.
Message msg = Message.obtain(mAddAttachmentHandler,
MSG_ADD_ATTACHMENT_FAILED, uri);
mAddAttachmentHandler.sendMessage(msg);
}
}
}
接下来会调用addVideo-->setAttachement()等方法进行设置附件,而这写操作均没有进行持久化操作。那么持久化操作在哪里呢?
当我们添加过附件之后,去查看或者播放幻灯片的时候会首先对附件内容进行持久化操作。这里我们调用了MessageUtils.java中的viewMmsMessageAttachment()方法。
public static void viewMmsMessageAttachment(final Activity activity, final Uri msgUri,
final SlideshowModel slideshow, final int requestCode, AsyncDialog asyncDialog) {
boolean isSimple = (slideshow == null) ? false : slideshow.isSimple();
if (isSimple) {
// In attachment-editor mode, we only ever have one slide.
MessageUtils.viewSimpleSlideshow(activity, slideshow);
} else {
// The user wants to view the slideshow. We have to persist the slideshow parts
// in a background task. If the task takes longer than a half second, a progress dialog
// is displayed. Once the PDU persisting is done, another runnable on the UI thread get
// executed to start the SlideshowActivity.
asyncDialog.runAsync(new Runnable() {
@Override
public void run() {
// If a slideshow was provided, save it to disk first.
if (slideshow != null) {
PduPersister persister = PduPersister.getPduPersister(activity);
try {
PduBody pb = slideshow.toPduBody();
persister.updateParts(msgUri, pb, null);
slideshow.sync(pb);
} catch (MmsException e) {
Log.e(TAG, "Unable to save message for preview");
return;
}
}
}
}, new Runnable() {
@Override
public void run() {
// Once the above background thread is complete, this runnable is run
// on the UI thread to launch the slideshow activity.
launchSlideshowActivity(activity, msgUri, requestCode);
}
}, R.string.building_slideshow_title);
}
}
上述代码中调用了PudPersister类中的updateParts()方法;
public void updateParts(Uri uri, PduBody body, HashMap<Uri, InputStream> preOpenedFiles)
throws MmsException {
try {
PduCacheEntry cacheEntry;
synchronized(PDU_CACHE_INSTANCE) {
if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
if (LOCAL_LOGV) {
Log.v(TAG, "updateParts: " + uri + " blocked by isUpdating()");
}
try {
PDU_CACHE_INSTANCE.wait();
} catch (InterruptedException e) {
Log.e(TAG, "updateParts: ", e);
}
cacheEntry = PDU_CACHE_INSTANCE.get(uri);
if (cacheEntry != null) {
((MultimediaMessagePdu) cacheEntry.getPdu()).setBody(body);
}
}
// Tell the cache to indicate to other callers that this item
// is currently being updated.
PDU_CACHE_INSTANCE.setUpdating(uri, true);
}
ArrayList<PduPart> toBeCreated = new ArrayList<PduPart>();
HashMap<Uri, PduPart> toBeUpdated = new HashMap<Uri, PduPart>();
int partsNum = body.getPartsNum();
StringBuilder filter = new StringBuilder().append('(');
for (int i = 0; i < partsNum; i++) {
PduPart part = body.getPart(i);
Uri partUri = part.getDataUri();
if ((partUri == null) || TextUtils.isEmpty(partUri.getAuthority())
|| !partUri.getAuthority().startsWith("mms")) {
toBeCreated.add(part);
} else {
toBeUpdated.put(partUri, part);
// Don't use 'i > 0' to determine whether we should append
// 'AND' since 'i = 0' may be skipped in another branch.
if (filter.length() > 1) {
filter.append(" AND ");
}
filter.append(Part._ID);
filter.append("!=");
DatabaseUtils.appendEscapedSQLString(filter, partUri.getLastPathSegment());
}
}
filter.append(')');
long msgId = ContentUris.parseId(uri);
// Remove the parts which doesn't exist anymore.
SqliteWrapper.delete(mContext, mContentResolver,
Uri.parse(Mms.CONTENT_URI + "/" + msgId + "/part"),
filter.length() > 2 ? filter.toString() : null, null);
// Create new parts which didn't exist before.
for (PduPart part : toBeCreated) {
persistPart(part, msgId, preOpenedFiles);
}
// Update the modified parts.
for (Map.Entry<Uri, PduPart> e : toBeUpdated.entrySet()) {
updatePart(e.getKey(), e.getValue(), preOpenedFiles);
}
} finally {
synchronized(PDU_CACHE_INSTANCE) {
PDU_CACHE_INSTANCE.setUpdating(uri, false);
PDU_CACHE_INSTANCE.notifyAll();
}
}
}
根据上述代码我们可以发现,如果是第一次,也就是没有持久化的时候则会进行insert操作,如果已经执行过insert则会进行update操作,在之前的一篇博客中已经描述过具体的修改方法,这里不再详细赘述,只是把修改的内容给展示出来,其他操作请参考我之前写的一篇博客,地址为:http://blog.csdn.net/huangyabin001/article/details/27523961
修改后:
private void updatePart(Uri uri, PduPart part, HashMap<Uri, InputStream> preOpenedFiles)
throws MmsException {
ContentValues values = new ContentValues(7);
int charset = part.getCharset();
if (charset != 0 ) {
values.put(Part.CHARSET, charset);
}
String contentType = null;
if (part.getContentType() != null) {
contentType = toIsoString(part.getContentType());
values.put(Part.CONTENT_TYPE, contentType);
} else {
throw new MmsException("MIME type of the part must be set.");
}
if (part.getFilename() != null) {
String fileName = new String(part.getFilename());
values.put(Part.FILENAME, fileName);
}
if (part.getName() != null) {
String name = new String(part.getName());
values.put(Part.NAME, name);
}
String value = null;
if (part.getContentDisposition() != null) {
value = toIsoString(part.getContentDisposition());
values.put(Part.CONTENT_DISPOSITION,value);
}
if (part.getContentId() != null) {
byte[] byteContentId=part.getContentId();
int encodeContentId=detectEncoding(byteContentId);
try{
switch(encodeContentId){
case GB2312:
value=new String(byteContentId,"GB2312");
break;
case ASCII:
value=new String(byteContentId,"ASCII");
break;
case UTF8:
value=new String(byteContentId,"UTF-8");
break;
case UNICODE:
value=new String(byteContentId,"Unicode");
break;
default:
value = toIsoString(byteContentId);
break;
}
values.put(Part.CONTENT_ID, value);
}catch(Exception e){
e.printStackTrace();
}
}
if (part.getContentLocation() != null) {
byte[] byteContentLocation=part.getContentLocation();
int encodeContentLocation=detectEncoding(byteContentLocation);
try{
switch(encodeContentLocation){
case GB2312:
value=new String(byteContentLocation,"GB2312");
break;
case ASCII:
value=new String(byteContentLocation,"ASCII");
break;
case UTF8:
value=new String(byteContentLocation,"UTF-8");
break;
case UNICODE:
value=new String(byteContentLocation,"Unicode");
break;
default:
value = toIsoString(byteContentLocation);
break;
}
values.put(Part.CONTENT_LOCATION,value);
}catch(Exception e){
e.printStackTrace();
}
}
SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null);
// Only update the data when:
// 1. New binary data supplied or
// 2. The Uri of the part is different from the current one.
if ((part.getData() != null)
|| (uri != part.getDataUri())) {
persistData(part, uri, contentType, preOpenedFiles);
}
}
修改前:
private void updatePart(Uri uri, PduPart part, HashMap<Uri, InputStream> preOpenedFiles)
throws MmsException {
ContentValues values = new ContentValues(7);
int charset = part.getCharset();
if (charset != 0 ) {
values.put(Part.CHARSET, charset);
}
String contentType = null;
if (part.getContentType() != null) {
contentType = toIsoString(part.getContentType());
values.put(Part.CONTENT_TYPE, contentType);
} else {
throw new MmsException("MIME type of the part must be set.");
}
if (part.getFilename() != null) {
String fileName = new String(part.getFilename());
values.put(Part.FILENAME, fileName);
}
if (part.getName() != null) {
String name = new String(part.getName());
values.put(Part.NAME, name);
}
Object value = null;
if (part.getContentDisposition() != null) {
value = toIsoString(part.getContentDisposition());
values.put(Part.CONTENT_DISPOSITION, (String) value);
}
if (part.getContentId() != null) {
value = toIsoString(part.getContentId());
values.put(Part.CONTENT_ID, (String) value);
}
if (part.getContentLocation() != null) {
value = toIsoString(part.getContentLocation());
values.put(Part.CONTENT_LOCATION, (String) value);
}
SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null);
// Only update the data when:
// 1. New binary data supplied or
// 2. The Uri of the part is different from the current one.
if ((part.getData() != null)
|| (uri != part.getDataUri())) {
persistData(part, uri, contentType, preOpenedFiles);
}
}
解决:编辑一条彩信,附件选择添加音频,返回到编辑界面选择play,不能播放,没有声音的更多相关文章
- 【登录异常解决】Ubuntu 输入正确的密码后重新返回到登陆界面
症状 Ubuntu 输入正确的密码后,黑屏一闪,重新返回到登陆界面. 原因一:主目录下的.Xauthority文件拥有者变成了root,从而以用户登陆的时候无法都取.Xauthority文件.说明:X ...
- android短彩信附件机制
将一些认识写下来,和大家交流一下,同时也方便自己复习. 用户可以通过附件按钮,添加附件.以添加幻灯片为例: 如果点击幻灯片,会走如下代码: ComposeMessageActivity.java pr ...
- 编辑技巧分享如何给PDF添加注释
纸质的文件想要添加注释就直接拿笔在上面添加就好了,那么电子文件要怎么添加注释呢,今天小编就以我们现在经常使用到的PDF文档来为大家分享怎么添加注释. 1. 我们需要在百度中搜索并下载并安装一款PD ...
- python全栈开发day61-django简单的出版社网站展示,添加,删除,编辑(单表的增删改查)
day61 django内容回顾: 1. 下载: pip install django==1.11.14 pip install -i 源 django==1.11.14 pycharm 2. 创建项 ...
- 【转载】win10解决设置默认打开方式不生效问题(双击每次都要选择默认打开程序)
win10解决设置默认打开方式不生效问题(双击每次都要选择默认打开程序) 以下文章 部分选自 https://blog.csdn.net/shan165310175/article/details/8 ...
- Winform 多个窗口编辑同一条数据同步的实现
场景: 一个主窗口中,可以在列表(DataGridView)里选中一条记录编辑,打开一个编辑窗口(非模态窗口),编辑窗口保存后需要刷新父窗口,由于编辑窗口是非模态窗口,如果打开了多个窗口,并且都是编辑 ...
- 关于Delphi cxGrid主从表中从表只能编辑第一条记录的问题
在Delphi cxGrid主从表中从表只能编辑第一条记录,这个问题是由于设置主从关联字段错误造成的. 从表DBtableView2的keyfieldnames,DetailKeyFieldNames ...
- 树莓派Zero W添加音频输出
编译:陈拓 chentuo@ms.xab.ac.cn 2018.06.07/2018.07.14 原文:Adding Basic Audio Ouput to Raspberry Pi Zero ht ...
- 安装Linux 16.04 时,选择好分区后,进到选择地点的界面后,总是闪退,退到最原始的界面
这两天装 Linux 系统,总是遇到一个很蛋疼的问题: 当你累死累活把分区什么的都设置好了之后,在输入了系统名字,开机密码那几项之后,再选择地点的时候(如:选择 "上海"),然后就 ...
随机推荐
- Ubuntu 14.04 更新gcc版本至4.9.2
参考: ubuntu 14.04 更新 gcc/g++ 4.9.2 Ubuntu 14.04 更新gcc版本至4.9.2 1.更新源,安装gcc v4.9.2 $ sudo add-apt-repos ...
- 【Coursera】Security Introduction -Ninth Week(2)
对于公钥系统,我们现在已经有了保证它 Confidentially 的一种方法:SSL.SSL利用了公钥的概念. 那么 who we are talking to? Integrity Certifi ...
- UVa 1630 串折叠
https://vjudge.net/problem/UVA-1630 题意: 给出一个由大写字母组成的长度为n的串,折叠成一个尽量短的串.例如:AAAAAAAAABABABCCD折叠成9(A)3(A ...
- hdu 2586 How far away ? 带权lca
How far away ? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) P ...
- python 重复元素排序
def counting_sort(array1, max_val): m = max_val + count = [] * m for a in array1: # count occurences ...
- python 阶乘
product= i= : product=i*product print('i=%d' %i,end='') print('\tproduct=%d' %product) i+= print('\n ...
- SQL Insert Case When Update
CREATE TABLE LoadTestTable ( ID INT IDENTITY(1,1), FIRSTNAME VARCHAR(50), LASTNAME VARCHAR(50), GEND ...
- MongoDB(课时10 数组)
3.4.2.5 数组查询 MongoDB里面支持数组保存,一旦支持数组保存,就需要对于数组的数据进行匹配. 范例:插入一部分数组内容 课程是数组的形式(截图时少截一条信息) 此时数据包含数组内容,而后 ...
- git问题解决(摘录)
https://blog.csdn.net/dxk539687357/article/details/54629274
- Java JDK5新特性-静态导入
2017-10-31 00:10:50 静态导入格式:import static 包名 ...类名.方法名: 也就说可以直接导入到方法名. 注意: 方法必须是静态的 如果有多个同名的静态方法,容易不知 ...