SlideshowModel

本文详细介绍了SlideshowModel类在多媒体消息展示与管理中的应用,包括消息大小限制、布局、内容解析与合成等关键功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
* Copyright (C) 2008 Esmertec AG.
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.android.mms.model;


import com.android.mms.ContentRestrictionException;
import com.android.mms.ExceedMessageSizeException;
import com.android.mms.MmsConfig;
import com.android.mms.R;
import com.android.mms.dom.smil.parser.SmilXmlSerializer;
import android.drm.mobile1.DrmException;
import com.android.mms.drm.DrmWrapper;
import com.android.mms.layout.LayoutManager;
import com.google.android.mms.ContentType;
import com.google.android.mms.MmsException;
import com.google.android.mms.pdu.GenericPdu;
import com.google.android.mms.pdu.MultimediaMessagePdu;
import com.google.android.mms.pdu.PduBody;
import com.google.android.mms.pdu.PduHeaders;
import com.google.android.mms.pdu.PduPart;
import com.google.android.mms.pdu.PduPersister;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.smil.SMILDocument;
import org.w3c.dom.smil.SMILElement;
import org.w3c.dom.smil.SMILLayoutElement;
import org.w3c.dom.smil.SMILMediaElement;
import org.w3c.dom.smil.SMILParElement;
import org.w3c.dom.smil.SMILRegionElement;
import org.w3c.dom.smil.SMILRootLayoutElement;

import android.content.ContentUris;
import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import com.android.mms.data.VCardComposer;
import android.content.ContentResolver;
import android.database.Cursor;
import com.google.android.mms.pdu.CharacterSets;
import android.pim.vcard.VCardConfig;





public class SlideshowModel extends Model
implements List<SlideModel>, IModelChangedObserver {
private static final String TAG = "Mms/slideshow";

private final LayoutModel mLayout;
private final ArrayList<SlideModel> mSlides;
private SMILDocument mDocumentCache;
private PduBody mPduBodyCache;
private int mCurrentMessageSize;
private Context mContext;

// amount of space to leave in a slideshow for text and overhead.
public static final int SLIDESHOW_SLOP = 1024;

private SlideshowModel(Context context) {
mLayout = new LayoutModel();
mSlides = new ArrayList<SlideModel>();
mContext = context;
}

private SlideshowModel (
LayoutModel layouts, ArrayList<SlideModel> slides,
SMILDocument documentCache, PduBody pbCache,
Context context) {
mLayout = layouts;
mSlides = slides;
mContext = context;

mDocumentCache = documentCache;
mPduBodyCache = pbCache;
for (SlideModel slide : mSlides) {
increaseMessageSize(slide.getSlideSize());
slide.setParent(this);
}
}

public static SlideshowModel createNew(Context context) {
return new SlideshowModel(context);
}

public static SlideshowModel createFromMessageUri(
Context context, Uri uri) throws MmsException {
return createFromPduBody(context, getPduBody(context, uri));
}

public static SlideshowModel createFromPduBody(Context context, PduBody pb) throws MmsException {
SMILDocument document = SmilHelper.getDocument(pb);

// Create root-layout model.
SMILLayoutElement sle = document.getLayout();
SMILRootLayoutElement srle = sle.getRootLayout();
int w = srle.getWidth();
int h = srle.getHeight();
if ((w == 0) || (h == 0)) {
w = LayoutManager.getInstance().getLayoutParameters().getWidth();
h = LayoutManager.getInstance().getLayoutParameters().getHeight();
srle.setWidth(w);
srle.setHeight(h);
}
RegionModel rootLayout = new RegionModel(
null, 0, 0, w, h);

// Create region models.
ArrayList<RegionModel> regions = new ArrayList<RegionModel>();
NodeList nlRegions = sle.getRegions();
int regionsNum = nlRegions.getLength();

for (int i = 0; i < regionsNum; i++) {
SMILRegionElement sre = (SMILRegionElement) nlRegions.item(i);
RegionModel r = new RegionModel(sre.getId(), sre.getFit(),
sre.getLeft(), sre.getTop(), sre.getWidth(), sre.getHeight(),
sre.getBackgroundColor());
regions.add(r);
}
LayoutModel layouts = new LayoutModel(rootLayout, regions);

// Create slide models.
SMILElement docBody = document.getBody();
NodeList slideNodes = docBody.getChildNodes();
int slidesNum = slideNodes.getLength();
ArrayList<SlideModel> slides = new ArrayList<SlideModel>(slidesNum);

for (int i = 0; i < slidesNum; i++) {
// FIXME: This is NOT compatible with the SMILDocument which is
// generated by some other mobile phones.
SMILParElement par = (SMILParElement) slideNodes.item(i);

// Create media models for each slide.
NodeList mediaNodes = par.getChildNodes();
int mediaNum = mediaNodes.getLength();
ArrayList<MediaModel> mediaSet = new ArrayList<MediaModel>(mediaNum);

for (int j = 0; j < mediaNum; j++) {
SMILMediaElement sme = null;
Node item = mediaNodes.item(j);
if (item instanceof SMILMediaElement) {
sme = (SMILMediaElement) item;
}
if (sme == null) {
continue;
}
try {
MediaModel media = MediaModelFactory.getMediaModel(
context, sme, layouts, pb);

/*
* This is for slide duration value set.
* If mms server does not support slide duration.
*/

if (!MmsConfig.getSlideDurationEnabled()) {
int mediadur = media.getDuration();
float dur = par.getDur();
if (dur == 0) {
mediadur = MmsConfig.getMinimumSlideElementDuration() * 1000;
media.setDuration(mediadur);
}

if ((int)mediadur / 1000 != dur) {
String tag = sme.getTagName();

if (ContentType.isVideoType(media.mContentType)
|| tag.equals(SmilHelper.ELEMENT_TAG_VIDEO)
|| ContentType.isAudioType(media.mContentType)
|| tag.equals(SmilHelper.ELEMENT_TAG_AUDIO)) {
/*
* add 1 sec to release and close audio/video
* for guaranteeing the audio/video playing.
* because the mmsc does not support the slide duration.
*/
par.setDur((float)mediadur / 1000 + 1);
} else {
/*
* If a slide has an image and an audio/video element
* and the audio/video element has longer duration than the image,
* The Image disappear before the slide play done. so have to match
* an image duration to the slide duration.
*/
if ((int)mediadur / 1000 < dur) {
media.setDuration((int)dur * 1000);
} else {
if ((int)dur != 0) {
media.setDuration((int)dur * 1000);
} else {
par.setDur((float)mediadur / 1000);
}
}
}
}
}

SmilHelper.addMediaElementEventListeners(
(EventTarget) sme, media);
mediaSet.add(media);
} catch (DrmException e) {
Log.e(TAG, e.getMessage(), e);
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
} catch (IllegalArgumentException e) {
Log.e(TAG, e.getMessage(), e);
}
}
//Begin Added xin.wu@archermind.com -20111118-
int slideModel_time=(int) (par.getDur() * 1000);
if(slideModel_time<1000){
slideModel_time=1000;
}
//End Added xin.wu@archermind.com -20111118-
SlideModel slide = new SlideModel(slideModel_time, mediaSet);
slide.setFill(par.getFill());
SmilHelper.addParElementEventListeners((EventTarget) par, slide);
slides.add(slide);
}

SlideshowModel slideshow = new SlideshowModel(layouts, slides, document, pb, context);
slideshow.registerModelChangedObserver(slideshow);
return slideshow;
}



//Begin modified by chenjiajian for optimize slideshow code 2012.3.5
public static SlideshowModel createFromPduBodySimple(Context context, PduBody pb) throws MmsException {
SMILDocument document = SmilHelper.getDocument(pb);

// Create root-layout model.
SMILLayoutElement sle = document.getLayout();
SMILRootLayoutElement srle = sle.getRootLayout();
int w = srle.getWidth();
int h = srle.getHeight();
if ((w == 0) || (h == 0)) {
w = LayoutManager.getInstance().getLayoutParameters().getWidth();
h = LayoutManager.getInstance().getLayoutParameters().getHeight();
srle.setWidth(w);
srle.setHeight(h);
}
RegionModel rootLayout = new RegionModel(
null, 0, 0, w, h);

// Create region models.
ArrayList<RegionModel> regions = new ArrayList<RegionModel>();
NodeList nlRegions = sle.getRegions();
int regionsNum = nlRegions.getLength();
Log.e("CJJ--ssm","regionsNum = "+regionsNum);
for (int i = 0; i < regionsNum; i++) {
SMILRegionElement sre = (SMILRegionElement) nlRegions.item(i);
RegionModel r = new RegionModel(sre.getId(), sre.getFit(),
sre.getLeft(), sre.getTop(), sre.getWidth(), sre.getHeight(),
sre.getBackgroundColor());
regions.add(r);
}
LayoutModel layouts = new LayoutModel(rootLayout, regions);

// Create slide models.
SMILElement docBody = document.getBody();
NodeList slideNodes = docBody.getChildNodes();
int slidesNum = slideNodes.getLength();
Log.e("CJJ--ssm","slidesNum = "+slidesNum);
ArrayList<SlideModel> slides = new ArrayList<SlideModel>(slidesNum);
//chenjiajian modify for load 2 or 1 slidesNum
// for (int i = 0; i < slidesNum; i++) {
int simpleCnt = 0;
if(slidesNum >2){
simpleCnt = 2;
}else{
simpleCnt = slidesNum;
}
for (int i = 0; i < simpleCnt; i++) {
// FIXME: This is NOT compatible with the SMILDocument which is
// generated by some other mobile phones.
SMILParElement par = (SMILParElement) slideNodes.item(i);
Log.e("CJJ--ssm", "par = " + par);

// Create media models for each slide.
NodeList mediaNodes = par.getChildNodes();
Log.e("CJJ--ssm", "mediaNodes = " + mediaNodes);
int mediaNum = mediaNodes.getLength();
// int mediaNum = 1;
Log.e("CJJ--ssm", "mediaNum = " + mediaNum);
ArrayList<MediaModel> mediaSet = new ArrayList<MediaModel>(mediaNum);

// add by chenjiajian for vCard

int partNum = pb.getPartsNum();
Log.e("CJJ--ssm", "partNum = " + partNum);
for (int p = 0; p < partNum; p++) {
try {
PduPart part = pb.getPart(p);
String type = new String(part.getContentType());
Log.e("CJJ--ssm", "370 type = " + type);
if (!ContentType.isImageType(type) && !ContentType.isVideoType(type)
&& !ContentType.isAudioType(type) && !type.startsWith("application/")
&& !type.equals(ContentType.TEXT_PLAIN)) {
Log.e("CJJ--ssm", "isVcard");
// String Location = new
// String(part.getContentLocation());
Uri uri = part.getDataUri();
Log.e("CJJ--ssm", "uri = " + uri);
if (null != uri) {

String mId = uri.getLastPathSegment();
VCardComposer mComposer = new VCardComposer(context,
VCardConfig.VCARD_TYPE_DEFAULT, false);
ContentResolver cr = context.getContentResolver();
Cursor mCursor = cr.query(uri, null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
// String vCardname = new
// String(part.getName());
// String vCardId = new
// String(part.getContentId());
String displayName = "Vcard";

if (part.getName() != null) {
displayName = new String(part.getName());
} else if (part.getContentId() != null) {
displayName = new String(part.getContentId());
}
Log.e("CJJ--ssm", "displayName = " + displayName);
// MediaModel media = new ContactModel(context,
// type,
// mCursor.getString(mCursor.getColumnIndex("display_name"))+".vcf",
// CharacterSets.ANY_CHARSET,
// mComposer.createOneEntryInternal(mId,null).getBytes());
MediaModel media = new ContactModel(context,
ContentType.TEXT_VCARD, displayName, part.getCharset(),
part.getData());
Log.e("CJJ--ssm", "mediaSet.add");
mediaSet.add(media);
mCursor.close();
}
}

}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.e(TAG, e.toString());
// e.printStackTrace();
}
}

// chenjiajian

for (int j = 0; j < mediaNum; j++) {
SMILMediaElement sme = null;
Node item = mediaNodes.item(j);
if (item instanceof SMILMediaElement) {
Log.e("CJJ--ssm", "370 instanceof SMILMediaElement");
sme = (SMILMediaElement) item;
}
Log.e("CJJ--ssm", "sme = " + sme);
if (sme == null) {
continue;
}
try {
Log.e("CJJ--ssm", "layouts = " + layouts);
MediaModel media = MediaModelFactory.getMediaModel(context, sme, layouts, pb);

SmilHelper.addMediaElementEventListeners((EventTarget) sme, media);
mediaSet.add(media);
} catch (DrmException e) {
Log.e(TAG, e.getMessage(), e);
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
} catch (IllegalArgumentException e) {
Log.e(TAG, e.getMessage(), e);
}
}
// Begin Added xin.wu@archermind.com -20111118-
int slideModel_time = (int) (par.getDur() * 1000);
if (slideModel_time < 1000) {
slideModel_time = 1000;
}
// End Added xin.wu@archermind.com -20111118-
SlideModel slide = new SlideModel(slideModel_time, mediaSet);
slide.setFill(par.getFill());
SmilHelper.addParElementEventListeners((EventTarget) par, slide);
slides.add(slide);
}


SlideshowModel slideshow = new SlideshowModel(layouts, slides, document, pb, context);
slideshow.registerModelChangedObserver(slideshow);
return slideshow;
}
//End modified by chenjiajian for optimize slideshow code 2012.3.5
public PduBody toPduBody() {
if (mPduBodyCache == null) {
mDocumentCache = SmilHelper.getDocument(this);
mPduBodyCache = makePduBody(mDocumentCache);
}
return mPduBodyCache;
}

private PduBody makePduBody(SMILDocument document) {
return makePduBody(null, document, false);
}

private PduBody makePduBody(Context context, SMILDocument document, boolean isMakingCopy) {
PduBody pb = new PduBody();

boolean hasForwardLock = false;
for (SlideModel slide : mSlides) {
for (MediaModel media : slide) {
if (isMakingCopy) {
if (media.isDrmProtected() && !media.isAllowedToForward()) {
hasForwardLock = true;
continue;
}
}

PduPart part = new PduPart();

if (media.isText()) {
TextModel text = (TextModel) media;
// Don't create empty text part.
if (TextUtils.isEmpty(text.getText())) {
continue;
}
// Set Charset if it's a text media.
part.setCharset(text.getCharset());
}

// Set Content-Type.
part.setContentType(media.getContentType().getBytes());
Log.e("CJJ","ContentType = "+media.getContentType());

String src = media.getSrc();
String location;
boolean startWithContentId = src.startsWith("cid:");
if (startWithContentId) {
location = src.substring("cid:".length());
} else {
location = src;
}

// Set Content-Location.
part.setContentLocation(location.getBytes());
Log.e("CJJ","location = "+location);
// Set Content-Id.
if (startWithContentId) {
//Keep the original Content-Id.
part.setContentId(location.getBytes());
}
else {
int index = location.lastIndexOf(".");
String contentId = (index == -1) ? location
: location.substring(0, index);
part.setContentId(contentId.getBytes());
Log.e("CJJ","contentId = "+contentId);
}
Log.e("CJJ","isDrmProtected = "+media.isDrmProtected()+" isText = "+media.isText()+" isImage = "+media.isImage()+" isContace = "+media.isContact());
if (media.isDrmProtected()) {
DrmWrapper wrapper = media.getDrmObject();
part.setDataUri(wrapper.getOriginalUri());
part.setData(wrapper.getOriginalData());
Log.e("CJJ","wrapper-uri = "+wrapper.getOriginalUri()+" wrapper-data = "+wrapper.getOriginalData());
} else if (media.isText()) {
part.setData(((TextModel) media).getText().getBytes());
} else if (media.isImage() || media.isVideo() || media.isAudio()) {
part.setDataUri(media.getUri());
}
//Add by jian.zhang for fix bug 391 2011.10.19 begin
else if (media.isContact()) {
ContactModel contact = (ContactModel) media;
part.setData((contact.getContact().getBytes()));
part.setCharset(contact.getCharset());
Log.e("CJJ","contact-Data = "+contact.getContact()+" contact-Charset = "+contact.getCharset());
// addSmil = false;
}
//Add by jian.zhang for fix bug 391 2011.10.19 end
else {
Log.w(TAG, "Unsupport media: " + media);
}

pb.addPart(part);
}
}

if (hasForwardLock && isMakingCopy && context != null) {
Toast.makeText(context,
context.getString(R.string.cannot_forward_drm_obj),
Toast.LENGTH_LONG).show();
document = SmilHelper.getDocument(pb);
}

// Create and insert SMIL part(as the first part) into the PduBody.
ByteArrayOutputStream out = new ByteArrayOutputStream();
SmilXmlSerializer.serialize(document, out);
PduPart smilPart = new PduPart();
smilPart.setContentId("smil".getBytes());
smilPart.setContentLocation("smil.xml".getBytes());
smilPart.setContentType(ContentType.APP_SMIL.getBytes());
smilPart.setData(out.toByteArray());
pb.addPart(0, smilPart);

return pb;
}

public PduBody makeCopy(Context context) {
return makePduBody(context, SmilHelper.getDocument(this), true);
}

public SMILDocument toSmilDocument() {
if (mDocumentCache == null) {
mDocumentCache = SmilHelper.getDocument(this);
}
return mDocumentCache;
}

public static PduBody getPduBody(Context context, Uri msg) throws MmsException {
PduPersister p = PduPersister.getPduPersister(context);
GenericPdu pdu = p.load(msg);

int msgType = pdu.getMessageType();
if ((msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)
|| (msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF)) {
return ((MultimediaMessagePdu) pdu).getBody();
} else {
throw new MmsException();
}
}

public void setCurrentMessageSize(int size) {
mCurrentMessageSize = size;
}

public int getCurrentMessageSize() {
return mCurrentMessageSize;
}

public void increaseMessageSize(int increaseSize) {
if (increaseSize > 0) {
mCurrentMessageSize += increaseSize;//modify by zhangfei
}
}

public void decreaseMessageSize(int decreaseSize) {
if (decreaseSize > 0) {
mCurrentMessageSize -= decreaseSize;
}
}

public LayoutModel getLayout() {
return mLayout;
}

//
// Implement List<E> interface.
//
public boolean add(SlideModel object) {
int increaseSize = object.getSlideSize();
checkMessageSize(increaseSize);

if ((object != null) && mSlides.add(object)) {
increaseMessageSize(increaseSize);
object.registerModelChangedObserver(this);
for (IModelChangedObserver observer : mModelChangedObservers) {
object.registerModelChangedObserver(observer);
}
notifyModelChanged(true);
return true;
}
return false;
}

public boolean addAll(Collection<? extends SlideModel> collection) {
throw new UnsupportedOperationException("Operation not supported.");
}

public void clear() {
if (mSlides.size() > 0) {
for (SlideModel slide : mSlides) {
slide.unregisterModelChangedObserver(this);
for (IModelChangedObserver observer : mModelChangedObservers) {
slide.unregisterModelChangedObserver(observer);
}
}
mCurrentMessageSize = 0;
mSlides.clear();
notifyModelChanged(true);
}
}

public boolean contains(Object object) {
return mSlides.contains(object);
}

public boolean containsAll(Collection<?> collection) {
return mSlides.containsAll(collection);
}

public boolean isEmpty() {
return mSlides.isEmpty();
}

public Iterator<SlideModel> iterator() {
return mSlides.iterator();
}

public boolean remove(Object object) {
if ((object != null) && mSlides.remove(object)) {
SlideModel slide = (SlideModel) object;
decreaseMessageSize(slide.getSlideSize());
slide.unregisterAllModelChangedObservers();
notifyModelChanged(true);
return true;
}
return false;
}

public boolean removeAll(Collection<?> collection) {
throw new UnsupportedOperationException("Operation not supported.");
}

public boolean retainAll(Collection<?> collection) {
throw new UnsupportedOperationException("Operation not supported.");
}

public int size() {
return mSlides.size();
}

public Object[] toArray() {
return mSlides.toArray();
}

public <T> T[] toArray(T[] array) {
return mSlides.toArray(array);
}

public void add(int location, SlideModel object) {
if (object != null) {
int increaseSize = object.getSlideSize();
checkMessageSize(increaseSize);

mSlides.add(location, object);
increaseMessageSize(increaseSize);
object.registerModelChangedObserver(this);
for (IModelChangedObserver observer : mModelChangedObservers) {
object.registerModelChangedObserver(observer);
}
notifyModelChanged(true);
}
}

public boolean addAll(int location,
Collection<? extends SlideModel> collection) {
throw new UnsupportedOperationException("Operation not supported.");
}

public SlideModel get(int location) {
return (location >= 0 && location < mSlides.size()) ? mSlides.get(location) : null;
}

public int indexOf(Object object) {
return mSlides.indexOf(object);
}

public int lastIndexOf(Object object) {
return mSlides.lastIndexOf(object);
}

public ListIterator<SlideModel> listIterator() {
return mSlides.listIterator();
}

public ListIterator<SlideModel> listIterator(int location) {
return mSlides.listIterator(location);
}

public SlideModel remove(int location) {
SlideModel slide = mSlides.remove(location);
if (slide != null) {
decreaseMessageSize(slide.getSlideSize());
slide.unregisterAllModelChangedObservers();
notifyModelChanged(true);
}
return slide;
}

public SlideModel set(int location, SlideModel object) {
SlideModel slide = mSlides.get(location);
if (null != object) {
int removeSize = 0;
int addSize = object.getSlideSize();
if (null != slide) {
removeSize = slide.getSlideSize();
}
if (addSize > removeSize) {
checkMessageSize(addSize - removeSize);
increaseMessageSize(addSize - removeSize);
} else {
decreaseMessageSize(removeSize - addSize);
}
}

slide = mSlides.set(location, object);
if (slide != null) {
slide.unregisterAllModelChangedObservers();
}

if (object != null) {
object.registerModelChangedObserver(this);
for (IModelChangedObserver observer : mModelChangedObservers) {
object.registerModelChangedObserver(observer);
}
}

notifyModelChanged(true);
return slide;
}

public List<SlideModel> subList(int start, int end) {
return mSlides.subList(start, end);
}

@Override
protected void registerModelChangedObserverInDescendants(
IModelChangedObserver observer) {
mLayout.registerModelChangedObserver(observer);

for (SlideModel slide : mSlides) {
slide.registerModelChangedObserver(observer);
}
}

@Override
protected void unregisterModelChangedObserverInDescendants(
IModelChangedObserver observer) {
mLayout.unregisterModelChangedObserver(observer);

for (SlideModel slide : mSlides) {
slide.unregisterModelChangedObserver(observer);
}
}

@Override
protected void unregisterAllModelChangedObserversInDescendants() {
mLayout.unregisterAllModelChangedObservers();

for (SlideModel slide : mSlides) {
slide.unregisterAllModelChangedObservers();
}
}

public void onModelChanged(Model model, boolean dataChanged) {
if (dataChanged) {
mDocumentCache = null;
mPduBodyCache = null;
}
}

public void sync(PduBody pb) {
for (SlideModel slide : mSlides) {
for (MediaModel media : slide) {
PduPart part = pb.getPartByContentLocation(media.getSrc());
if (part != null) {
media.setUri(part.getDataUri());
}
}
}
}

public void checkMessageSize(int increaseSize) throws ContentRestrictionException {
ContentRestriction cr = ContentRestrictionFactory.getContentRestriction();
cr.checkMessageSize(mCurrentMessageSize, increaseSize, mContext.getContentResolver());
}

/**
* Determines whether this is a "simple" slideshow.
* Criteria:
* - Exactly one slide
* - Exactly one multimedia attachment, but no audio
* - It can optionally have a caption
*/
public boolean isSimple() {
// There must be one (and only one) slide.
if (size() != 1)
return false;

SlideModel slide = get(0);
// The slide must have either an image or video, but not both.
if (!(slide.hasImage() ^ slide.hasVideo()))
return false;

// No audio allowed.
if (slide.hasAudio())
return false;

//Add by jian.zhang for fix bug 391 2011.10.19 begin
if (slide.hasContact()) {
return false;
}
//Add by jian.zhang for fix bug 391 2011.10.19 end

return true;
}

/**
* Make sure the text in slide 0 is no longer holding onto a reference to the text
* in the message text box.
*/
public void prepareForSend() {
if (size() == 1) {
TextModel text = get(0).getText();
if (text != null) {
text.cloneText();
}
}
}

// Benig added by chenjiajian@newpostcom.com.cn.-20111018-
/**
*add Resize() method and call before getCurrentMessageSize(),
*because mms picture size was wrong.
*/
public void Resize() {//this method modify by zhangfei 2011-12-13 for
int totalSize = 0;
int count = mSlides.size();
if (count == 1) {
for (MediaModel media : mSlides.get(0)) {
totalSize += media.getMediaSize();
}
} else {
ArrayList<Uri> uris = new ArrayList<Uri>();
for (SlideModel slide : mSlides) {
for (MediaModel media : slide) {
if (uris.contains(media.getUri())) {
continue;
} else {
uris.add(media.getUri());
// Begin: modify by huangle@npte.local to fix cr 1345, 1315--2012.03.08
//totalSize += media.getMediaSize();
totalSize += (Math.ceil(((float)media.getMediaSize())/((float)4096)))*4096 ;
// End: modify by huangle@npte.local to fix cr 1345, 1315--2012.03.08
}
}
}
uris.clear();
uris = null;
}

if (totalSize > MmsConfig.getMaxMessageSize()) {
throw new ExceedMessageSizeException(
"After compressing pictures, message too big");
}
setCurrentMessageSize(totalSize);
}
// End added by chenjiajian@newpostcom.com.cn.-20111018-

/**
* Resize all the resizeable media objects to fit in the remaining size of the slideshow.
* This should be called off of the UI thread.
*
* @throws MmsException, ExceedMessageSizeException
*/
public void finalResize(Uri messageUri) throws MmsException, ExceedMessageSizeException {
// Log.v(TAG, "Original message size: " + getCurrentMessageSize() + " getMaxMessageSize: "
// + MmsConfig.getMaxMessageSize());

// Figure out if we have any media items that need to be resized and total up the
// sizes of the items that can't be resized.
int resizableCnt = 0;
int fixedSizeTotal = 0;
for (SlideModel slide : mSlides) {
for (MediaModel media : slide) {
if (media.getMediaResizable()) {
++resizableCnt;
} else {
fixedSizeTotal += media.getMediaSize();
}
}
}
if (resizableCnt > 0) {
int remainingSize = MmsConfig.getMaxMessageSize() - fixedSizeTotal - SLIDESHOW_SLOP;
if (remainingSize <= 0) {
throw new ExceedMessageSizeException("No room for pictures");
}
long messageId = ContentUris.parseId(messageUri);
int bytesPerMediaItem = remainingSize / resizableCnt;
// Resize the resizable media items to fit within their byte limit.
for (SlideModel slide : mSlides) {
for (MediaModel media : slide) {
if (media.getMediaResizable()) {
//Begin Modify by xin.wu@archermind.com -20111027-
// if(media.getContentType().equals("image/gif")&&(media.getMediaSize()<MmsConfig.getMaxMessageSize())){
if(media.getMediaSize()<MmsConfig.getMaxMessageSize()){
// if media is image/gif and size less than 300k, will not resize and compress
}
else{
//delete by zhangfei 2011-11-10 start
Log.d(TAG, "finalResize");
media.resizeMedia(bytesPerMediaItem, messageId);
//delete by zhangfei 2011-11-10 end
}
//End Modify by xin.wu@archermind.com -20111027-
}
}
}
// One last time through to calc the real message size.
int totalSize = 0;
//modify by zhangfei 2012-01-02 for calculate the attachment size start
// for (SlideModel slide : mSlides) {
// for (MediaModel media : slide) {
// totalSize += media.getMediaSize();
// }
// }
Resize();
totalSize = getCurrentMessageSize();
//modify by zhangfei 2012-01-02 for calculate the attachment size end
// Log.v(TAG, "New message size: " + totalSize + " getMaxMessageSize: "
// + MmsConfig.getMaxMessageSize());

if (totalSize > MmsConfig.getMaxMessageSize()) {
throw new ExceedMessageSizeException("After compressing pictures, message too big");
}
setCurrentMessageSize(totalSize);

onModelChanged(this, true); // clear the cached pdu body
PduBody pb = toPduBody();
// This will write out all the new parts to:
// /data/data/com.android.providers.telephony/app_parts
// and at the same time delete the old parts.
PduPersister.getPduPersister(mContext).updateParts(messageUri, pb);
}
}

}


android 15中报错:// CRASH: com.android.mms (pid 32001) // Short Msg: java.lang.NullPointerException // Long Msg: java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference // Build Label: SONIM/X53001/X530:15/X53.0-01-15.0-99.01.11/jenkins:userdebug/test-keys // Build Changelist: jenkins // Build Time: 1754634422000 // java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference // at com.android.mms.ui.AttachmentViewActivity.onDataLoadFinished(AttachmentViewActivity.java:281) // at com.android.mms.ui.BaseAttachmentViewActivity$GetDataAsyncTask.onPostExecute(BaseAttachmentViewActivity.java:222) // at com.android.mms.ui.BaseAttachmentViewActivity$GetDataAsyncTask.onPostExecute(BaseAttachmentViewActivity.java:190) // at android.os.AsyncTask.finish(AsyncTask.java:771) // at android.os.AsyncTask.-$$Nest$mfinish(Unknown Source:0) // at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:788) // at android.os.Handler.dispatchMessage(Handler.java:107) // at android.os.Looper.loopOnce(Looper.java:232) // at android.os.Looper.loop(Looper.java:317) // at android.app.ActivityThread.main(ActivityThread.java:8794) // at java.lang.reflect.Method.invoke(Native Method) // at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580) // at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:892) ,具体代码如下:AttachmentViewActivity.java:/* * Sonim Technologies, Inc. CONFIDENTIAL * Copyright (c) 2017 All Rights Reserved. * * The source code contained or described herein and all documents * related to the source code ("Material") is property of Sonim * Technologies, Inc. and its affiliates, may be covered by U.S. * or Foreign Patents or patents in process, and is protected by trade * secret or copyright law. No part of the Material may be used, * copied, reproduced, modified, published, uploaded, posted, * transmitted, distributed, or disclosed in any way without * prior written permission by Sonim Technologies, Inc. * * Unless required by applicable law or agreed to in writing, * the Materials are provided "AS IS," and WITHOUT WARRANTIES * OR CONDITIONS OF ANY KIND, either express or implied. No license * under any patent, copyright, trade secret or other * intellectual property right is granted to or conferred upon you * by disclosure or delivery of the Material, either expressly, by * implication, inducement, estoppel or otherwise. Any license * under such intellectual property rights must be express and * approved by Sonim Technologies, Inc. in writing. * */ package com.android.mms.ui; import android.content.Context; import android.content.Intent; import android.os.Bundle; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import android.text.Html; import android.util.DisplayMetrics; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.Menu; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import com.android.mms.R; import com.android.mms.model.MediaModel; import com.android.mms.model.MediaWithTextModel; import com.android.mms.ui.multipleviews.BaseViewFragment; import com.android.mms.ui.multipleviews.VideoViewFragment; import com.google.android.mms.ContentType; import java.util.ArrayList; public class AttachmentViewActivity extends BaseAttachmentViewActivity { private static final String TAG = "AttachmentViewActivity"; static final int SAVE_SLIDER_ATTACHMENT_PERMISSION_REQUEST_CODE = 2017; private static final int DEFAULT_VISIBLE_LIST_COUNT = 3; private static final int DEFAULT_RECYCLER_VIEW_HEIGHT = 0; private static final int RECYCLER_VIEW_DEVICE_PORTION_ON_DEVICE_HEIGHT = 4; private static final boolean CONTAINER_FULLVIEW_MODE_VISIBLE = true; private static final boolean CONTAINER_FULLVIEW_MODE_INVISIBLE = false; private static final String VIEW_VCARD = "VIEW_VCARD_FROM_MMS"; private static final String KEY_PACKAGE_NAME = "calling_package_name"; private static final String PACKAGE_NAME = "com.android.mms"; private static final String EXTRA_SINGLE_ITEM = "SingleItemOnly"; private LinearLayout mDotsLayout; private TextView[] mDotsTextview; private SlidesAdapter mSlidesAdapter; private RecyclerView mSlidesRecyclerView; /** * Default recycler view height will be zero. Based on Device height it will be calculate the * recyclerview height dynamically. */ private int mRecyclerViewHeight = 0; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); if (MessageUtils.checkPermissionsIfNeeded(this)) { return; } setContentView(R.layout.attachment_view_activity); new GetDataAsyncTask(this).execute(); } private void initView() { mSelectedAttachmentContainer = (LinearLayout) findViewById(R.id.frameLayout_container); mDotsLayout = (LinearLayout) findViewById(R.id.dots_layout); mSlidesRecyclerView = (RecyclerView) findViewById(R.id.slides_recycler_view); calculateRecyclerViewHeight(); resetRecyclerViewHeight(mRecyclerViewHeight); RecyclerView.LayoutManager layoutManager = new LinearLayoutManagerWrapper(getApplicationContext(), LinearLayoutManager.HORIZONTAL, false); mSlidesRecyclerView.setLayoutManager(layoutManager); mSlidesRecyclerView.setItemAnimator(new DefaultItemAnimator()); mSlidesAdapter = new SlidesAdapter(mMediaWithTextModelList, this); mSlidesRecyclerView.setAdapter(mSlidesAdapter); // << [DNL-7826] 20210422 JunYiLin >> mSlidesAdapter.setOnDataSetChangedListener(mDataSetChangedListener); // << [DNL-7080] 20210330 JunYiLin << mSlidesRecyclerView.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { updateNavBar(getResources().getStringArray(R.array.setNavBar_highlight_attachments_view_in_slideshow)); } } }); // [DNL-7080] >> } /** * prepare display dots layout */ private void displayDotsLayout() { if (mDotsTextview == null) { if (mMediaWithTextModelList.size() % DEFAULT_VISIBLE_LIST_COUNT == 0) { mDotsTextview = new TextView[mMediaWithTextModelList.size() / DEFAULT_VISIBLE_LIST_COUNT]; } else { mDotsTextview = new TextView[ (mMediaWithTextModelList.size() / DEFAULT_VISIBLE_LIST_COUNT) + 1]; } for (int i = 0; i < mDotsTextview.length; i++) { TextView dotTextView = new TextView(this); mDotsTextview[i] = dotTextView; mDotsTextview[i].setText(Html.fromHtml(getResources(). getString(R.string.dots_text_design))); mDotsTextview[i].setTextSize(getResources().getDimension(R.dimen.dot_text_design_size)); mDotsTextview[i].setTextColor(getResources().getColor(R.color.dot_inactive)); Log.v(TAG, "mDotsTextview text: "+mDotsTextview[i].getText()); mDotsLayout.addView(mDotsTextview[i]); } changeDotsColor(0); } Log.d(TAG,"fxj 147"); // Message UABT-1662 Haifei.Liao remove the dot layout BEGIN mDotsLayout.setVisibility(View.GONE); // Message UABT-1662 Haifei.Liao remove the dot layout END } @Override public void onRequestPermissionsResult(final int requestCode, final String permissions[], final int[] grantResults) { if (requestCode == SAVE_SLIDER_ATTACHMENT_PERMISSION_REQUEST_CODE) { if (MessageUtils.hasStoragePermission()) { //TODO: Check for permission enabled or not } else { Toast.makeText(this, R.string.no_permission_save_attachment_to_storage, Toast.LENGTH_SHORT).show(); } } } /** * change dots color whenever focus going to change left to right or right to left * @param currentPage */ private void changeDotsColor(int currentPage) { if (mDotsTextview == null) { return; } int focus = currentPage / DEFAULT_VISIBLE_LIST_COUNT; if (focus > 0) { mDotsTextview[focus - 1].setTextColor(getResources().getColor(R.color.dot_inactive)); } if (focus < mDotsTextview.length - 1) { mDotsTextview[focus + 1].setTextColor(getResources().getColor(R.color.dot_inactive)); } mDotsTextview[focus].setTextColor(getResources().getColor(R.color.dot_active)); } @Override public void onBackPressed() { /** * When click on back button check for is it in full view mode or not. If it is in full view mode * adjust to normal mode without close application. If it is in normal mode close this activity */ if (mSlidesRecyclerView.getLayoutParams() != null && mSlidesRecyclerView.getLayoutParams().height == DEFAULT_RECYCLER_VIEW_HEIGHT) { if (isSingleSlideMode()) { finish(); } else { resetRecyclerViewHeight(CONTAINER_FULLVIEW_MODE_INVISIBLE); } } else { super.onBackPressed(); } } @Override public void onItemClick(int position) { /** * If seleted mediaModel is Vcard or Vcal open there respective actions * else adjust current view as full view. */ MediaModel mediaModel = mMediaWithTextModelList.get(position).getMediaModel(); if (mediaModel != null) { if (mediaModel.isVcard()) { Intent intent = new Intent(Intent.ACTION_VIEW); // we need open the saved part. intent.setDataAndType(mediaModel.getUri(), ContentType.TEXT_VCARD.toLowerCase()); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // distinguish view vcard from mms or contacts. intent.putExtra(VIEW_VCARD, true); Intent openInChooser = Intent.createChooser(intent, getString(R.string.action_header)); startActivity(openInChooser); } else if (mediaModel.isVcal()) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.putExtra(EXTRA_SINGLE_ITEM, true); // So we don't see "surrounding" images in Gallery intent.putExtra(KEY_PACKAGE_NAME, PACKAGE_NAME); String contentType; contentType = mediaModel.getContentType(); intent.setDataAndType(mediaModel.getUri(), contentType); startActivity(intent); } else { resetRecyclerViewHeight(CONTAINER_FULLVIEW_MODE_VISIBLE); } } } @Override public void onLoadContainerView(int position) { super.onLoadContainerView(position); updateCurrentPosition(position); Log.v(TAG, "Attachment no fragment loaded till now onLoadContainerView"); changeDotsColor(position); } /** * Update mediaWithTextModel on mediaModel and text available * @param mediaModel * @param message */ @Override public void onDataUpdate(final MediaModel mediaModel, final String message) { runOnUiThread(new Runnable() { @Override public void run() { if(mActualNumberOfSlides == mNumberOfSlidesLoaded) { onDataInsert(mediaModel, message); } else { MediaWithTextModel mediaWithTextModel = mMediaWithTextModelList.get(mNumberOfSlidesLoaded); mediaWithTextModel.setMediaModel(mediaModel); mediaWithTextModel.setMessageText(message); mMediaWithTextModelList.set(mNumberOfSlidesLoaded, mediaWithTextModel); mSlidesAdapter.notifyItemChanged(mNumberOfSlidesLoaded); mNumberOfSlidesLoaded = mNumberOfSlidesLoaded + 1; } } }); } /** * Method for once data loads done this method will trigger. Handle on Main Thread */ @Override public void onDataLoadFinished() { Log.v(TAG, "Attachment onDataLoadFinished media list size is " + mMediaWithTextModelList.size()); removeEmptySlideObjects(); displayDotsLayout(); } @Override public void setInitialSlideSize(int size) { super.setInitialSlideSize(size); mMediaWithTextModelList = new ArrayList<MediaWithTextModel>(size); for(int i = 0; i < size; i ++) { mMediaWithTextModelList.add(new MediaWithTextModel(null,null)); } runOnUiThread(new Runnable() { @Override public void run() { initView(); } }); } @Override public void onDataInsert(final MediaModel mediaModel, final String message) { runOnUiThread(new Runnable() { @Override public void run() { Log.v(TAG, "Attachment onDataInsert"); MediaWithTextModel mediaWithTextModel = new MediaWithTextModel(message, mediaModel); mMediaWithTextModelList.add(mediaWithTextModel); mSlidesAdapter.notifyItemInserted(mMediaWithTextModelList.size() - 1); } }); } @Override public void onDataRemove(final int position) { mSlidesAdapter.notifyItemRemoved(position); } /** * sometimes slidemodel will return empty mediamodel list */ private void removeEmptySlideObjects() { //check for number of slides reached or not. If not reached then remove dummy viewholder from recyclerview runOnUiThread(new Runnable() { @Override public void run() { if(mActualNumberOfSlides > mNumberOfSlidesLoaded) { mMediaWithTextModelList.remove(mNumberOfSlidesLoaded); mNumberOfSlidesLoaded = mNumberOfSlidesLoaded + 1; onDataRemove(mMediaWithTextModelList.size()); removeEmptySlideObjects(); } } }); } public static class LinearLayoutManagerWrapper extends LinearLayoutManager { public LinearLayoutManagerWrapper(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); } @Override public boolean supportsPredictiveItemAnimations() { return false; } } /** * Calculate recycler view height using the device height * eg: if device height is 400 then recycleViewHeight = 400/4 * (Here 4 is portion of value). finally recyclerViewHeight = 100 */ private void calculateRecyclerViewHeight() { DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); int height = displayMetrics.heightPixels; mRecyclerViewHeight = (int) (height / RECYCLER_VIEW_DEVICE_PORTION_ON_DEVICE_HEIGHT ); } public void resetRecyclerViewHeight(boolean isViewEntered) { Log.d(TAG, "base resetRecyclerViewHeight isEnter = " + isViewEntered); BaseViewFragment baseFragment = (BaseViewFragment) getFragmentManager() .findFragmentById(R.id.selected_attachment_container); if (isViewEntered) { resetRecyclerViewHeight(DEFAULT_RECYCLER_VIEW_HEIGHT); mDotsLayout.setVisibility(View.GONE); if (baseFragment != null) { baseFragment.onPlayMedia(); } } else { resetRecyclerViewHeight(mRecyclerViewHeight); mDotsLayout.setVisibility(View.VISIBLE); if (baseFragment != null) { baseFragment.onStopMedia(); } } mSlidesRecyclerView.requestLayout(); } private void resetRecyclerViewHeight(int height) { mSlidesRecyclerView.getLayoutParams().height = height; mSlidesRecyclerView.requestLayout(); } /** * When click play all menu item readjust view from full view to normal */ @Override public void onPlayAllMenuItemSelect() { if (mSlidesRecyclerView.getLayoutParams().height == DEFAULT_RECYCLER_VIEW_HEIGHT) { resetRecyclerViewHeight(CONTAINER_FULLVIEW_MODE_INVISIBLE); } } @Override public void playMediaInFullView() { resetRecyclerViewHeight(CONTAINER_FULLVIEW_MODE_VISIBLE); } @Override public boolean dispatchKeyEvent(KeyEvent event) { BaseViewFragment baseFragment = (BaseViewFragment) getFragmentManager() .findFragmentById(R.id.selected_attachment_container); if(baseFragment instanceof VideoViewFragment) { VideoViewFragment videoViewFragment = (VideoViewFragment) baseFragment; videoViewFragment.onKeyEvent(); } return super.dispatchKeyEvent(event); } @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); invalidateOptionsMenu(); return true; } // [DNL-7080] 20210330 JunYiLin << @Override public boolean onKeyUp(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_MENU: saveAllAttachment(); break; case KeyEvent.KEYCODE_MULTIFUNC_CENTER: playAllSlideShow(); break; case KeyEvent.KEYCODE_MULTIFUNC_RIGHT: saveAttachment(); break; } return super.onKeyUp(keyCode, event); } @Override protected void onResume() { super.onResume(); updateNavBar(this.getResources().getStringArray(R.array.setNavBar_highlight_attachments_view_in_slideshow)); } // [DNL-7080] >> },BaseAttachmentViewActivity.java:/* * Sonim Technologies, Inc. CONFIDENTIAL * Copyright (c) 2017 All Rights Reserved. * * The source code contained or described herein and all documents * related to the source code ("Material") is property of Sonim * Technologies, Inc. and its affiliates, may be covered by U.S. * or Foreign Patents or patents in process, and is protected by trade * secret or copyright law. No part of the Material may be used, * copied, reproduced, modified, published, uploaded, posted, * transmitted, distributed, or disclosed in any way without * prior written permission by Sonim Technologies, Inc. * * Unless required by applicable law or agreed to in writing, * the Materials are provided "AS IS," and WITHOUT WARRANTIES * OR CONDITIONS OF ANY KIND, either express or implied. No license * under any patent, copyright, trade secret or other * intellectual property right is granted to or conferred upon you * by disclosure or delivery of the Material, either expressly, by * implication, inducement, estoppel or otherwise. Any license * under such intellectual property rights must be express and * approved by Sonim Technologies, Inc. in writing. * */ package com.android.mms.ui; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.ContentValues; import android.content.Intent; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.provider.Telephony; import android.util.Log; import android.os.Environment; import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; // << [DNL-795] 20210113 JunYiLin >> import android.view.KeyEvent; import android.webkit.MimeTypeMap; import android.widget.LinearLayout; import android.widget.Toast; import com.android.mms.MmsApp; import com.android.mms.R; import com.android.mms.drm.DrmUtils; import com.android.mms.model.MediaWithTextModel; import com.android.mms.model.MediaModel; import com.android.mms.model.SlideModel; import com.android.mms.model.SlideshowModel; import com.android.mms.model.SmilHelper; import com.android.mms.transaction.MessagingNotification; import com.android.mms.ui.multipleviews.AudioViewFragment; import com.android.mms.ui.multipleviews.BaseViewFragment; import com.android.mms.ui.multipleviews.IAttachmentSelection; import com.android.mms.ui.multipleviews.ImageViewFragment; import com.android.mms.ui.multipleviews.VcardVcalViewFragment; import com.android.mms.ui.multipleviews.VideoViewFragment; import com.android.mms.util.Utils; import com.google.android.mms.ContentType; import com.google.android.mms.MmsException; import com.google.android.mms.util.SqliteWrapper; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; import java.util.List; public abstract class BaseAttachmentViewActivity extends Activity implements IAttachmentSelection { private static final String TAG = BaseAttachmentViewActivity.class.getSimpleName(); private static final int SINGLE_SLIDE_MODEL_SIZE = 1; private static final String NO_SPACE_ERROR = "ENOSPC"; private static boolean mNoSpace = false; public static final int MENU_PLAY = 1; public static final int MENU_PAUSE = 2; public static final int MENU_RESUME = 3; public static final int MENU_PLAY_ALL = 4; public static final int MENU_STOP = 5; public static final int MENU_SAVE_ATTACHMENT = 6; public static final int MENU_SAVE_ALL_ATTACHMENTS = 7; public LinearLayout mSelectedAttachmentContainer; public List<MediaWithTextModel> mMediaWithTextModelList; private boolean mSingleSlideMode = false; private boolean mPlayAllMode = false; private boolean mEditSlideShowMode = false; private int mCurrentMediaPosition = 0; public int mActualNumberOfSlides, mNumberOfSlidesLoaded; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } private void markAsReadIfNeed() { Intent intent = getIntent(); boolean unread = intent.getBooleanExtra("unread", false); Uri uri = intent.getData(); if (unread) { ContentValues values = new ContentValues(2); values.put(Telephony.Mms.SEEN, MessageUtils.MESSAGE_SEEN); values.put(Telephony.Mms.READ, MessageUtils.MESSAGE_READ); SqliteWrapper.update(this, getContentResolver(), uri, values, null, null); MessagingNotification.blockingUpdateNewMessageIndicator( this, MessagingNotification.THREAD_NONE, false); } } @Override public void onLoadContainerView(int position) { MediaWithTextModel mediaWithTextModel = mMediaWithTextModelList.get(position); overrideContainer(mediaWithTextModel); } @Override public void onLoadContainerView(MediaWithTextModel customMediaModel) { overrideContainer(customMediaModel); } // When switching between the fragments update mCurrentMediaPosition // with selected media position public void updateCurrentPosition(int currentMediaPosition) { mCurrentMediaPosition = currentMediaPosition; } private void overrideContainer(MediaWithTextModel mediaWithTextModel) { if (!isFinishing() && !isDestroyed()) { FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); MediaModel mediaModel = mediaWithTextModel.getMediaModel(); switch (mediaModel.getTag()) { case SmilHelper.ELEMENT_TAG_TEXT: fragmentTransaction.replace(R.id.selected_attachment_container, ImageViewFragment.newInstance(mediaWithTextModel), null); break; case SmilHelper.ELEMENT_TAG_IMAGE: fragmentTransaction.replace(R.id.selected_attachment_container, ImageViewFragment.newInstance(mediaWithTextModel), null); break; case SmilHelper.ELEMENT_TAG_AUDIO: fragmentTransaction.replace(R.id.selected_attachment_container, AudioViewFragment.newInstance(mediaWithTextModel), null); break; case SmilHelper.ELEMENT_TAG_VIDEO: fragmentTransaction.replace(R.id.selected_attachment_container, VideoViewFragment.newInstance(mediaWithTextModel), null); break; case SmilHelper.ELEMENT_TAG_REF: if (mediaModel.getContentType().toLowerCase().equals(ContentType.TEXT_VCARD. toLowerCase()) || mediaModel.getContentType().toLowerCase(). equals(ContentType.TEXT_VCALENDAR.toLowerCase())) { fragmentTransaction.replace(R.id.selected_attachment_container, VcardVcalViewFragment.newInstance(mediaWithTextModel), null); } break; default: Log.v(TAG,"default attachment type case"); } fragmentTransaction.commit(); } } public boolean isSingleSlideMode() { return mSingleSlideMode; } public void setSingleSlideMode(boolean mSingleSlideMode) { this.mSingleSlideMode = mSingleSlideMode; } static class GetDataAsyncTask extends AsyncTask<Void, Void, Void> { private WeakReference<BaseAttachmentViewActivity> attachmentViewActivityWeakReference; public GetDataAsyncTask(BaseAttachmentViewActivity baseAttachmentViewActivity) { attachmentViewActivityWeakReference = new WeakReference(baseAttachmentViewActivity); } @Override protected Void doInBackground(Void... voids) { Log.v(TAG, "GetDataAsyncTask doInBackground"); BaseAttachmentViewActivity activity = attachmentViewActivityWeakReference.get(); if (activity != null) { try { Intent intent = activity.getIntent(); Uri uri = intent.getData(); SlideshowModel.createFromMessageUri(activity, uri); } catch (MmsException e) { Log.e(TAG, "Cannot present the slide show.", e); } activity.markAsReadIfNeed(); } else { Log.v(TAG, "GetDataAsyncTask Activity is null "); } return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); BaseAttachmentViewActivity activity = attachmentViewActivityWeakReference.get(); if (activity != null) { activity.onDataLoadFinished(); } } } /** * Update mediaWithTextModelList on slideModel available * @param slideModel * @param currentSlide */ @Override public void onDataUpdate(SlideModel slideModel, int currentSlide) { String message = slideModel.getText() != null ? slideModel.getText().getText() : null; if (slideModel.size() == SINGLE_SLIDE_MODEL_SIZE && slideModel.get(0).isText()) { if (mActualNumberOfSlides > mNumberOfSlidesLoaded) { onDataUpdate(slideModel.get(0), message); } else { onDataInsert(slideModel.get(0), message); } } else { for (int j = 0; j < slideModel.size(); j++) { MediaModel mediaModel = slideModel.get(j); Log.d(TAG, "Attachment prepareSlideData MediaModel contentType = " + mediaModel.getContentType()); if (mediaModel != null && !mediaModel.isText()) { Log.d(TAG, "Attachment prepareSlideData adding MediaWithTextModel "); if (mActualNumberOfSlides > mNumberOfSlidesLoaded) { onDataUpdate(mediaModel, message); } else { onDataInsert(mediaModel, message); } } } } } @Override public void setInitialSlideSize(int size) { Log.v(TAG, "Attachment setSlideShowSize size " + size); mActualNumberOfSlides = size; } public IAttachmentSelection getIAttachmentSelection() { return this; } public boolean isPlayAllMode() { return mPlayAllMode; } public void setPlayAllMode(boolean mPlayAllMode) { this.mPlayAllMode = mPlayAllMode; } @Override public void onPlayNextSlide() { } //[DNL-795] 20210220 JunYiLin << /* mark original @Override public boolean onPrepareOptionsMenu(Menu menu) { menu.clear(); BaseViewFragment baseFragment = (BaseViewFragment) getFragmentManager(). findFragmentById(R.id.selected_attachment_container); if(baseFragment != null) { baseFragment.onMenuUpdate(menu); } if(mMediaWithTextModelList != null && mMediaWithTextModelList.size() > 1) { menu.add(0, MENU_PLAY_ALL, 0,R.string.play_all); } menu.add(0, MENU_SAVE_ATTACHMENT, 0,R.string.save_attachment); if(mMediaWithTextModelList != null && mMediaWithTextModelList.size() > 1) { menu.add(0, MENU_SAVE_ALL_ATTACHMENTS, 0, R.string.save_all_attachments); } return true; } */ // [DNL-795] >> @Override public boolean onOptionsItemSelected(MenuItem item) { BaseViewFragment baseFragment = null; switch (item.getItemId()) { case MENU_PLAY_ALL: onPlayAllMenuItemSelect(); Intent intent = new Intent(this, AttachmentPlayAllActivity.class); intent.setData(getIntent().getData()); startActivity(intent); break; case MENU_SAVE_ATTACHMENT: saveAttachment(); break; case MENU_SAVE_ALL_ATTACHMENTS: saveAllAttachment(); break; case MENU_PLAY: playMediaInFullView(); baseFragment = (BaseViewFragment) getFragmentManager() .findFragmentById(R.id.selected_attachment_container); baseFragment.onPlayMedia(); break; case MENU_PAUSE: baseFragment = (BaseViewFragment) getFragmentManager() .findFragmentById(R.id.selected_attachment_container); baseFragment.onPauseMedia(); break; case MENU_RESUME: baseFragment = (BaseViewFragment) getFragmentManager() .findFragmentById(R.id.selected_attachment_container); baseFragment.onResumeMedia(); break; default: return super.onOptionsItemSelected(item); } return true; } // [DNL-7080] 20210330 JunYiLin << public void saveAllAttachment() { /* mark original private void saveAllAttachment(){ */ // [DNL-7080] int resId; boolean isCopied = copyMedia(); if(isCopied){ resId = R.string.save_all_attachment_success; }else{ resId = mNoSpace ? R.string.space_low_message : R.string.save_attachment_fail; } Toast.makeText(BaseAttachmentViewActivity.this, resId, Toast.LENGTH_SHORT).show(); } // [DNL-795] 20210113 JunYiLin << public void saveAttachment() { /* mark original private void saveAttachment(){ */ // [DNL-795] >> int resId; boolean isCopied = copyPart(mMediaWithTextModelList.get(mCurrentMediaPosition)); if(isCopied){ resId = R.string.save_attachment_success; }else{ resId = mNoSpace ? R.string.space_low_message : R.string.save_attachment_fail; } Toast.makeText(BaseAttachmentViewActivity.this, resId, Toast.LENGTH_SHORT).show(); } /** * Copies media from an Mms to the "download" directory on the SD card. If any of the parts * are audio types, drm'd or not, they're copied to the "Ringtones" directory. */ private boolean copyMedia() { boolean result = true; if (mMediaWithTextModelList == null) { return false; } for(int i = 0; i < mMediaWithTextModelList.size(); i++) { // all parts have to be successful for a valid result. result &= copyPart(mMediaWithTextModelList.get(i)); } return result; } private boolean copyPart(MediaWithTextModel customMediaModel) { // [DNL-8241] 20210423 JunYiLin << if (MessageUtils.checkIsPhoneMemoryFull(BaseAttachmentViewActivity.this)) { mNoSpace = true; return false; } // [DNL-8241] >> mNoSpace = false; MediaModel mediaModel = customMediaModel.getMediaModel(); Uri uri = mediaModel.getUri(); String type = new String(mediaModel.getContentType()); boolean isDrm = DrmUtils.isDrmType(type); if (isDrm) { type = MmsApp.getApplication().getDrmManagerClient() .getOriginalMimeType(uri); } if (!ContentType.isImageType(type) && !ContentType.isVideoType(type) && !ContentType.isAudioType(type) && !(ContentType.TEXT_VCARD.toLowerCase().equals(type.toLowerCase())) && !(ContentType.TEXT_VCALENDAR.toLowerCase().equals(type.toLowerCase())) && !(ContentType.AUDIO_OGG.toLowerCase().equals(type.toLowerCase()))) { return true; // we only save pictures, videos, and sounds. Skip the text parts, // the app (smil) parts, and other type that we can't handle. // Return true to pretend that we successfully saved the part so // the whole save process will be counted a success. } InputStream input = null; FileOutputStream fout = null; try { input = getContentResolver().openInputStream(uri); if (input instanceof FileInputStream) { FileInputStream fin = (FileInputStream) input; String fileName = mediaModel.getSrc(); File originalFile = new File(fileName); fileName = originalFile.getName(); // Strip the full path of where the "part" is // stored down to just the leaf filename. // For every media the default saving directory should be 'Download'. String dir = Utils.getStoragePath(this) + "/" + Environment.DIRECTORY_DOWNLOADS + "/"; String extension; int index; if ((index = fileName.lastIndexOf('.')) == -1) { extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(type); } else { extension = fileName.substring(index + 1, fileName.length()); fileName = fileName.substring(0, index); } if (isDrm) { extension += DrmUtils.getConvertExtension(type); } // Remove leading periods. The gallery ignores files starting with a period. if (!TextUtils.isEmpty(fileName)) { fileName = fileName.trim(); fileName = fileName.replaceAll("^\\.", ""); } File file = getUniqueDestination(dir + fileName, extension); // make sure the path is valid and directories created for this file. File parentFile = file.getParentFile(); if (!parentFile.exists() && !parentFile.mkdirs()) { Log.e(TAG, "[MMS] copyPart: mkdirs for " + parentFile.getPath() + " failed!"); return false; } fout = new FileOutputStream(file); byte[] buffer = new byte[8000]; int size = 0; while ((size=fin.read(buffer)) != -1) { fout.write(buffer, 0, size); } // Notify other applications listening to scanner events // that a media file has been added to the sd card sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file))); } } catch (IOException e) { // Ignore Log.e(TAG, "IOException caught while opening or reading stream", e); if(e.getMessage().contains(NO_SPACE_ERROR)){ mNoSpace = true; } return false; } finally { if (null != input) { try { input.close(); } catch (IOException e) { // Ignore Log.e(TAG, "IOException caught while closing stream", e); return false; } } if (null != fout) { try { fout.close(); } catch (IOException e) { // Ignore Log.e(TAG, "IOException caught while closing stream", e); return false; } } } return true; } private File getUniqueDestination(String base, String extension) { File file = new File(base + "." + extension); for (int i = 2; file.exists(); i++) { file = new File(base + "_" + i + "." + extension); } return file; } @Override public void onPlayAllMenuItemSelect() { } @Override public void playMediaInFullView() {} public boolean isEditSlideShowMode() { return mEditSlideShowMode; } public void setEditSlideShowMode(boolean editSlideShowMode) { this.mEditSlideShowMode = editSlideShowMode; } // << [DNL-7080] 20210330 JunYiLin << public void updateNavBar(String[] str) { if (str.length > 0) { MessageUtils.setNavigationBarName(this, str); } } public void playAllSlideShow() { Intent intent = new Intent(this, AttachmentPlayAllActivity.class); intent.setData(getIntent().getData()); startActivity(intent); } // [DNL-7080] >> // [DNL-7826] 20210422 JunYiLin << public final SlidesAdapter.OnDataSetChangedListener mDataSetChangedListener = new SlidesAdapter.OnDataSetChangedListener() { @Override public void onHighLightItem(int position) { playAudioMedia(position); } }; public void playAudioMedia(int position) { MediaModel mediaModel = mMediaWithTextModelList.get(position).getMediaModel(); if (mediaModel != null && mediaModel.isAudio()) { BaseViewFragment baseFragment = (BaseViewFragment) getFragmentManager().findFragmentById(R.id.selected_attachment_container); if (baseFragment != null) { baseFragment.onPlayMedia(); } } } // [DNL-7826] >> }以上报错,怎么在上述代码上具体修改
最新发布
08-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值