package com.netease.nim.uikit.session.activity; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.provider.MediaStore; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPager; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.Toast; import com.netease.nim.uikit.R; import com.netease.nim.uikit.common.activity.UI; import com.netease.nim.uikit.common.ui.dialog.CustomAlertDialog; import com.netease.nim.uikit.common.ui.dialog.CustomAlertDialog.onSeparateItemClickListener; import com.netease.nim.uikit.common.ui.imageview.BaseZoomableImageView; import com.netease.nim.uikit.common.ui.imageview.ImageGestureListener; import com.netease.nim.uikit.common.util.C; import com.netease.nim.uikit.common.util.file.AttachmentStore; import com.netease.nim.uikit.common.util.media.BitmapDecoder; import com.netease.nim.uikit.common.util.media.ImageUtil; import com.netease.nim.uikit.common.util.storage.StorageUtil; import com.netease.nimlib.sdk.AbortableFuture; import com.netease.nimlib.sdk.NIMClient; import com.netease.nimlib.sdk.Observer; import com.netease.nimlib.sdk.RequestCallback; import com.netease.nimlib.sdk.msg.MessageBuilder; import com.netease.nimlib.sdk.msg.MsgService; import com.netease.nimlib.sdk.msg.MsgServiceObserve; import com.netease.nimlib.sdk.msg.attachment.ImageAttachment; import com.netease.nimlib.sdk.msg.constant.AttachStatusEnum; import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; import com.netease.nimlib.sdk.msg.model.IMMessage; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * 查看聊天消息原图 * Created by huangjun on 2015/3/6. */ public class WatchMessagePictureActivity extends UI { private static final String INTENT_EXTRA_IMAGE = "INTENT_EXTRA_IMAGE"; private static final String TAG = WatchMessagePictureActivity.class.getSimpleName(); private Handler handler; private IMMessage message; private List<IMMessage> imageMsgList = new ArrayList<>(); private int firstDisplayImageIndex = 0; private boolean newPageSelected = false; private View loadingLayout; private BaseZoomableImageView image; protected CustomAlertDialog alertDialog; private ViewPager imageViewPager; private PagerAdapter adapter; private AbortableFuture downloadFuture; public static void start(Context context, IMMessage message) { Intent intent = new Intent(); intent.putExtra(INTENT_EXTRA_IMAGE, message); intent.setClass(context, WatchMessagePictureActivity.class); context.startActivity(intent); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.nim_watch_picture_activity); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); this.message = (IMMessage) getIntent().getSerializableExtra(INTENT_EXTRA_IMAGE); findViews(); queryImageMessages(); handler = new Handler(); registerObservers(true); } @Override protected void onDestroy() { registerObservers(false); imageViewPager.setAdapter(null); if (downloadFuture != null) { downloadFuture.abort(); downloadFuture = null; } super.onDestroy(); } private void queryImageMessages() { IMMessage anchor = MessageBuilder.createEmptyMessage(message.getSessionId(), message.getSessionType(), 0); NIMClient.getService(MsgService.class).queryMessageListByType(MsgTypeEnum.image, anchor, Integer.MAX_VALUE).setCallback(new RequestCallback<List<IMMessage>>() { @Override public void onSuccess(List<IMMessage> param) { imageMsgList.addAll(param); Collections.reverse(imageMsgList); setDisplayIndex(); setViewPagerAdapter(); } @Override public void onFailed(int code) { Log.i(TAG, "query msg by type failed, code:" + code); } @Override public void onException(Throwable exception) { } }); } // 设置第一个选中的图片index private void setDisplayIndex() { for (int i = 0; i < imageMsgList.size(); i++) { IMMessage imageObject = imageMsgList.get(i); if (compareObjects(message, imageObject)) { firstDisplayImageIndex = i; break; } } } protected boolean compareObjects(IMMessage t1, IMMessage t2) { return (t1.getUuid().equals(t2.getUuid())); } private void findViews() { alertDialog = new CustomAlertDialog(this); loadingLayout = findViewById(R.id.loading_layout); imageViewPager = (ViewPager) findViewById(R.id.view_pager_image); } private void setViewPagerAdapter() { adapter = new PagerAdapter() { @Override public int getCount() { return imageMsgList == null ? 0 : imageMsgList.size(); } @Override public void notifyDataSetChanged() { super.notifyDataSetChanged(); } @Override public void destroyItem(ViewGroup container, int position, Object object) { View layout = (View) object; BaseZoomableImageView iv = (BaseZoomableImageView) layout.findViewById(R.id.watch_image_view); iv.clear(); container.removeView(layout); } @Override public boolean isViewFromObject(View view, Object object) { return (view == object); } @Override public Object instantiateItem(ViewGroup container, int position) { ViewGroup layout; layout = (ViewGroup) LayoutInflater.from(WatchMessagePictureActivity.this).inflate(R.layout.image_layout_multi_touch, null); layout.setBackgroundColor(Color.BLACK); container.addView(layout); layout.setTag(position); if (position == firstDisplayImageIndex) { onViewPagerSelected(position); } return layout; } @Override public int getItemPosition(Object object) { return POSITION_NONE; } }; imageViewPager.setAdapter(adapter); imageViewPager.setOffscreenPageLimit(2); imageViewPager.setCurrentItem(firstDisplayImageIndex); imageViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (positionOffset == 0f && newPageSelected) { newPageSelected = false; onViewPagerSelected(position); } } @Override public void onPageSelected(int position) { newPageSelected = true; } @Override public void onPageScrollStateChanged(int state) { } }); } private void onViewPagerSelected(int position) { if (downloadFuture != null) { downloadFuture.abort(); downloadFuture = null; } updateCurrentImageView(position); onImageViewFound(image); requestOriImage(imageMsgList.get(position)); } // 初始化每个view的image protected void updateCurrentImageView(final int position) { View currentLayout = imageViewPager.findViewWithTag(position); if (currentLayout == null) { ViewCompat.postOnAnimation(imageViewPager, new Runnable() { @Override public void run() { updateCurrentImageView(position); } }); return; }; image = (BaseZoomableImageView) currentLayout.findViewById(R.id.watch_image_view); } // 若图片已下载,直接显示图片;若图片未下载,则下载图片 private void requestOriImage(IMMessage msg) { if (isOriginImageHasDownloaded(msg)) { onDownloadSuccess(msg); return; } // async download original image onDownloadStart(msg); message = msg; // 下载成功之后,判断是否是同一条消息时需要使用 downloadFuture = NIMClient.getService(MsgService.class).downloadAttachment(msg, false); } private boolean isOriginImageHasDownloaded(final IMMessage message) { if (message.getAttachStatus() == AttachStatusEnum.transferred && !TextUtils.isEmpty(((ImageAttachment) message.getAttachment()).getPath())) { return true; } return false; } /** * ******************************** 设置图片 ********************************* */ private void setThumbnail(IMMessage msg) { String thumbPath = ((ImageAttachment) msg.getAttachment()).getThumbPath(); String path = ((ImageAttachment) msg.getAttachment()).getPath(); Bitmap bitmap = null; if (!TextUtils.isEmpty(thumbPath)) { bitmap = BitmapDecoder.decodeSampledForDisplay(thumbPath); bitmap = ImageUtil.rotateBitmapInNeeded(thumbPath, bitmap); } else if (!TextUtils.isEmpty(path)) { bitmap = BitmapDecoder.decodeSampledForDisplay(path); bitmap = ImageUtil.rotateBitmapInNeeded(path, bitmap); } if (bitmap != null) { image.setImageBitmap(bitmap); return; } image.setImageBitmap(ImageUtil.getBitmapFromDrawableRes(getImageResOnLoading())); } private void setImageView(final IMMessage msg) { String path = ((ImageAttachment) msg.getAttachment()).getPath(); if (TextUtils.isEmpty(path)) { image.setImageBitmap(ImageUtil.getBitmapFromDrawableRes(getImageResOnLoading())); return; } Bitmap bitmap = BitmapDecoder.decodeSampledForDisplay(path, false); bitmap = ImageUtil.rotateBitmapInNeeded(path, bitmap); if (bitmap == null) { Toast.makeText(this, R.string.picker_image_error, Toast.LENGTH_LONG).show(); image.setImageBitmap(ImageUtil.getBitmapFromDrawableRes(getImageResOnFailed())); } else { image.setImageBitmap(bitmap); } } private int getImageResOnLoading() { return R.drawable.nim_image_default; } private int getImageResOnFailed() { return R.drawable.nim_image_download_failed; } /** * ********************************* 下载 **************************************** */ private void registerObservers(boolean register) { NIMClient.getService(MsgServiceObserve.class).observeMsgStatus(statusObserver, register); } private Observer<IMMessage> statusObserver = new Observer<IMMessage>() { @Override public void onEvent(IMMessage msg) { if (!msg.isTheSame(message) || isDestroyedCompatible()) { return; } if (isOriginImageHasDownloaded(msg)) { onDownloadSuccess(msg); } else if (msg.getAttachStatus() == AttachStatusEnum.fail) { onDownloadFailed(); } } }; private void onDownloadStart(final IMMessage msg) { setThumbnail(msg); if(TextUtils.isEmpty(((ImageAttachment)msg.getAttachment()).getPath())){ loadingLayout.setVisibility(View.VISIBLE); } else { loadingLayout.setVisibility(View.GONE); } } private void onDownloadSuccess(final IMMessage msg) { loadingLayout.setVisibility(View.GONE); handler.post(new Runnable() { @Override public void run() { setImageView(msg); } }); } private void onDownloadFailed() { loadingLayout.setVisibility(View.GONE); image.setImageBitmap(ImageUtil.getBitmapFromDrawableRes(getImageResOnFailed())); Toast.makeText(this, R.string.download_picture_fail, Toast.LENGTH_LONG).show(); } /** * ***********************************图片点击事件******************************************* */ // 设置图片点击事件 protected void onImageViewFound(BaseZoomableImageView imageView) { imageView.setImageGestureListener(new ImageGestureListener() { @Override public void onImageGestureSingleTapConfirmed() { onImageViewTouched(); } @Override public void onImageGestureLongPress() { showWatchPictureAction(); } @Override public void onImageGestureFlingDown() { finish(); } }); } // 图片单击 protected void onImageViewTouched() { finish(); } // 图片长按 protected void showWatchPictureAction() { if (alertDialog.isShowing()) { alertDialog.dismiss(); return; } alertDialog.clearData(); String path = ((ImageAttachment) message.getAttachment()).getThumbPath(); if (TextUtils.isEmpty(path)) { return; } String title; if (!TextUtils.isEmpty(((ImageAttachment) message.getAttachment()).getPath())) { title = getString(R.string.save_to_device); alertDialog.addItem(title, new onSeparateItemClickListener() { @Override public void onClick() { savePicture(); } }); } alertDialog.show(); } // 保存图片 public void savePicture() { ImageAttachment attachment = (ImageAttachment) message.getAttachment(); String path = attachment.getPath(); if (TextUtils.isEmpty(path)) { return; } String srcFilename = attachment.getFileName(); //默认jpg String extension = TextUtils.isEmpty(attachment.getExtension()) ? "jpg" : attachment.getExtension(); srcFilename += ("." + extension); String picPath = StorageUtil.getSystemImagePath(); String dstPath = picPath + srcFilename; if (AttachmentStore.copy(path, dstPath) != -1) { try { ContentValues values = new ContentValues(2); values.put(MediaStore.Images.Media.MIME_TYPE, C.MimeType.MIME_JPEG); values.put(MediaStore.Images.Media.DATA, dstPath); getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); Toast.makeText(WatchMessagePictureActivity.this, getString(R.string.picture_save_to), Toast.LENGTH_LONG).show(); } catch (Exception e) { // may be java.lang.UnsupportedOperationException Toast.makeText(WatchMessagePictureActivity.this, getString(R.string.picture_save_fail), Toast.LENGTH_LONG).show(); } } else { Toast.makeText(WatchMessagePictureActivity.this, getString(R.string.picture_save_fail), Toast.LENGTH_LONG).show(); } } }