您的位置:首页 > 其它

解决:编辑一条彩信,附件选择添加音频,返回到编辑界面选择play,不能播放,没有声音

2014-06-10 17:15 429 查看
【操作步骤】:编辑一条彩信,附件选择添加音频(外部音频),返回到编辑界面选择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);

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐