MMS附件播放查看与附件保存

来源:互联网 发布:java登陆注册实现 编辑:程序博客网 时间:2024/04/29 23:55

Android4.2

1. MediaModel    代表一项附件。实现接口EventListener。

2. SlideModel      代表一页幻灯片。实现接口List<MediaModel>, EventListener

3. SlideshowModel  代表所有幻灯片。实现接口List<SlideModel>, IModelChangedObserver。


SlideshowActivity用于播放幻灯片,在Oncreate中SlideshowModel.createFromMessageUri(this, msg)构建SlideshowModel对象:

通过uri获取PduBody对象,通过PduBody获取SMILLayoutElement,接着解析smil文件。利用MediaModelFactory获取MediaMode

    public static MediaModel getMediaModel(Context context,            SMILMediaElement sme, LayoutModel layouts, PduBody pb)
并给每一个获取到的MediaModel注册EventListener接口(好像没用,注册者没被引用),最后也把SlideModel给注册了。
                    SmilHelper.addMediaElementEventListeners(                            (EventTarget) sme, media);
获取所有SlideModel后构建SlideshowModel对象,并注册自己的IModelChangedObserver接口,返回SlideshowModel。


接下来

        mSlideView = (SlideView) findViewById(R.id.slide_view);        PresenterFactory.getPresenter("SlideshowPresenter", this, mSlideView, model);
在SlideshowPresenter类的构造中调用了父类Presenter的构造并在其中
        mModel = model;        mModel.registerModelChangedObserver(this);
其中model为SlideShowModel,Presenter实现接口IModelChangedObserver,也就是说把SlideshowPresenter注册到SlideShowModel。

Model注册方法如下:

    public void registerModelChangedObserver(IModelChangedObserver observer) {        if (!mModelChangedObservers.contains(observer)) {            mModelChangedObservers.add(observer);            registerModelChangedObserverInDescendants(observer);        }    }
在SlideShowModel中的registerModelChangedObserverInDescendants方法内给所有SlideModel注册了接口:
    protected void registerModelChangedObserverInDescendants(            IModelChangedObserver observer) {        mLayout.registerModelChangedObserver(observer);        for (SlideModel slide : mSlides) {            slide.registerModelChangedObserver(observer);        }    }
而在SlideModel内给所有MediaMode注册了这个observer。

也就是说,SlideShowModel与之内所有要显示的对象都注册了SlideshowPresenter的接口。

调用Model的notifyModelChanged则触发接口的调用,调用到SlideshowPresenter的onModelChanged方法。在onModelChanged方法内根据调用的MediaMode不同对SlideView调用不同的显示。


由前面得知每一个MediaModel的EventListener接口都被注册了,接口方法为handleEvent,而在子MediaModel比如ImageMode中的handleEvent方法中都调用了notifyModelChanged方法。


幻灯片播放流程:

构建播放器SmilPlayer对象。由SlideshowModel获取SMILDocument对象

mSmilDoc = SmilHelper.getDocument(model);

获取过程中对每一个MediaMode注册addMediaElementEventListeners((EventTarget) sme, media);接着初始化播放器

 mSmilPlayer.init(mSmilDoc);
    public synchronized void init(ElementTime root) {        mRoot = root;        mAllEntries = getTimeline(mRoot, 0, Long.MAX_VALUE);        mMediaTimeUpdatedEvent = ((DocumentEvent) mRoot).createEvent("Event");        mMediaTimeUpdatedEvent.initEvent(MEDIA_TIME_UPDATED_EVENT, false, false);        mActiveElements = new ArrayList<ElementTime>();    }
调用SmilPlayer的play方法启动子线程,在run方法里依次播放每一页幻灯片,切换时调用waitForEntry(long interval)方法,此方法内
            ((EventTarget) mRoot).dispatchEvent(mMediaTimeUpdatedEvent);
分发所有EventListener接口事件。

二、附件的命名及保存

在MmsProvider中进行命名,在PduPersister中进行附件保存。

以saveDraft为开始流程为例:按流程将调用到SlideShowModel的finalResize方法中,此方法调用

PduPersister.getPduPersister(mContext).updateParts(messageUri, pb, null);
开始附件保存流程,其中第三个参数是InputStream的hashMap。在此方法内调用persistPart方法,persistPart方法内
       Uri res = SqliteWrapper.insert(mContext, mContentResolver, uri, values);
接着调用persistData方法保存数据,如果此前传来的InputStream的hashMap不为空,以uri为key获取流,否则以uri通过openInputStream获取流。

文件命名在insert数据时provider中的insert方法中进行,尾字符串为cl字段内容,名称:parts_时间_cl字段内容。


三、ContentProvider的openInputStream与openOutputStream

重写ContentProvider的openFile方法实现这两个功能。如下Mms的provider

    @Override    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {        // TODO do we even need this anymore?        ParcelFileDescriptor fd;        int match = sURLMatcher.match(uri);        if (Log.isLoggable(TAG, Log.VERBOSE)) {            Log.d(TAG, "openFile: uri=" + uri + ", mode=" + mode);        }        switch (match) {            default:                fd = openFileHelper(uri, mode);        }        return fd;    }
openFileHelper方法使用"_data"作为文件路径字段,如果自定义字段存储文件路径,则不使用系统提供的openFileHelper方法或者重写此方法。