zoukankan      html  css  js  c++  java
  • 解决:编辑一条彩信,附件选择添加音频,返回到编辑界面选择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);
            }
        }



  • 相关阅读:
    solr中facet、group查询
    Solr开发文档
    Java的Properties类和读取.properties文件
    CentOS RPM安装MySQL-5.6
    C#中的 IList, ICollection ,IEnumerable 和 IEnumerator
    Linq to Xml
    Linq查询
    XDocument和XmlDocument的区别
    关于扩展方法
    今天刚刚开通了园子
  • 原文地址:https://www.cnblogs.com/bill-technology/p/4130920.html
Copyright © 2011-2022 走看看