欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

即时通讯App|发送图片消息的实现

程序员文章站 2022-07-12 14:17:09
...

即时通讯App——发送图片消息的实现

前置知识:

1、onActivityResult()的用法

假如有两个Activity A,B。如今需要从A的界面跳转到B的界面执行相应的操作。操作执行完毕之后,从B的界面跳转回A的界面,或许还会返回一些数据交给A处理,这样的数据交流可以利用回调函数onActivityResult()实现。

即时通讯App|发送图片消息的实现

业务流程

1、读取相机/相册图片

2、发送图片消息

3、photoview预览

1、读取相机实现代码

/**
 * 相机
 * 如果头像上传,可以支持裁剪,自行增加
 *
 * @param mActivity
 */
public void toCamera(Activity mActivity) {
    try {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        String fileName = simpleDateFormat.format(new Date());
        tempFile = new File(Environment.getExternalStorageDirectory(), fileName + ".jpg");
        //兼容Android N
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            imageUri = Uri.fromFile(tempFile);
        } else {
            //利用FileProvider
            imageUri = FileProvider.getUriForFile(mActivity,
                    mActivity.getPackageName() + ".fileprovider", tempFile);
            //添加权限
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION |
                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        }
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        mActivity.startActivityForResult(intent, CAMEAR_REQUEST_CODE);
    } catch (Exception e) {
        Toast.makeText(mActivity, "无法打开相机", Toast.LENGTH_SHORT).show();
        e.printStackTrace();
    }
}

2、跳转到相册实现代码

/**
 * 跳转到相册
 *
 * @param mActivity
 */
public void toAlbum(Activity mActivity) {
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType("image/*");
    mActivity.startActivityForResult(intent, ALBUM_REQUEST_CODE);
}

以上两个方法封装在FileHelper文件的帮助类中。

然后在聊天Activity中处理FileHelper回调的图片数据

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == Activity.RESULT_OK) {
        if (requestCode == FileHelper.CAMEAR_REQUEST_CODE) {
            uploadFile = FileHelper.getInstance().getTempFile();
        } else if (requestCode == FileHelper.ALBUM_REQUEST_CODE) {
            Uri uri = data.getData();
            if (uri != null) {
                //String path = uri.getPath();
                //获取真实的地址
                String path = FileHelper.getInstance().getRealPathFromURI(this, uri);
                //LogUtils.e("path:" + path);
                if (!TextUtils.isEmpty(path)) {
                    uploadFile = new File(path);
                }
            }
        } 
        if (uploadFile != null) {
            //发送图片消息
            CloudManager.getInstance().sendImageMessage(yourUserId, uploadFile);
            //更新列表
            addImage(1, uploadFile);
            uploadFile = null;
        }
    }
    super.onActivityResult(requestCode, resultCode, data);
}

发送图片调用融云SDK,下面有一个callback,由于我们省略了发送图片的进度,是否成功等回调,直接写在service中就可以了。如果需要具体回调处理,则把回调放置到传参列表即可。

private RongIMClient.SendImageMessageCallback sendImageMessageCallback = new RongIMClient.SendImageMessageCallback() {
    @Override
    public void onAttached(Message message) {
        LogUtils.i("onAttached");
    }

    @Override
    public void onError(Message message, RongIMClient.ErrorCode errorCode) {
        LogUtils.i("onError:" + errorCode);
    }

    @Override
    public void onSuccess(Message message) {
        LogUtils.i("onSuccess");
    }

    @Override
    public void onProgress(Message message, int i) {
        LogUtils.i("onProgress:" + i);
    }
};

/**
 * 发送图片消息
 *
 * @param targetId 对方ID
 * @param file     文件
 */
public void sendImageMessage(String targetId, File file) {
    ImageMessage imageMessage = ImageMessage.obtain(Uri.fromFile(file), Uri.fromFile(file), true);
    RongIMClient.getInstance().sendImageMessage(
            Conversation.ConversationType.PRIVATE,
            targetId,
            imageMessage,
            null,
            null,
            sendImageMessageCallback);
}

adapter多数据绑定

mChatAdapter = new CommonAdapter<>(mList, new CommonAdapter.OnMoreBindDataListener<ChatModel>() {
    @Override
    public int getItemType(int position) {
        return mList.get(position).getType();
    }

    @Override
    public void onBindViewHolder(final ChatModel model, CommonViewHolder viewHolder, int type, int position) {
      //布局文件中的控件,设置相应的数据,通过chatModel中的type来区分是左边还是右边的布局的控件
        switch (model.getType()) {
            case TYPE_LEFT_IMAGE:
                viewHolder.setImageUrl(ChatActivity.this, R.id.iv_left_img, model.getImgUrl());
                viewHolder.setImageUrl(ChatActivity.this, R.id.iv_left_photo, yourUserPhoto);
                viewHolder.getView(R.id.iv_left_img).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ImagePreviewActivity.startActivity(
                                ChatActivity.this, true, model.getImgUrl());
                    }
                });

                break;
            case TYPE_RIGHT_IMAGE://右边的是本地文件
                if (TextUtils.isEmpty(model.getImgUrl())) {
                    if (model.getLocalFile() != null) {
                        //加载本地文件
                        viewHolder.setImageFile(ChatActivity.this, R.id.iv_right_img, model.getLocalFile());
                        viewHolder.getView(R.id.iv_right_img).setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                ImagePreviewActivity.startActivity(
                                        ChatActivity.this, false, model.getLocalFile().getPath());
                            }
                        });
                    }
                } else {
                    viewHolder.setImageUrl(ChatActivity.this, R.id.iv_right_img, model.getImgUrl());
                     viewHolder.setImageUrl(ChatActivity.this, R.id.iv_right_photo, meUserPhoto);
                    viewHolder.getView(R.id.iv_right_img).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            ImagePreviewActivity.startActivity(
                                    ChatActivity.this, true, model.getImgUrl());
                        }
                    });
                }
         
                break;
        }
    }
	//布局文件,通过chatModel中的type来区分是左边还是右边的布局
    @Override
    public int getLayoutId(int type) {
        } else if (type == TYPE_LEFT_IMAGE) {
            return R.layout.layout_chat_left_img;
        } else if (type == TYPE_RIGHT_IMAGE) {
            return R.layout.layout_chat_right_img;
        }
        return 0;
    }
});
mChatView.setAdapter(mChatAdapter);
  /**
     * 添加数据的基类
     *
     * @param model
     */
    private void baseAddItem(ChatModel model) {
        long currentTime = System.currentTimeMillis();
        LogUtils.e("currentTime:" + currentTime);
        if (CommonUtils.isEmpty(mList)) {
            //本地逻辑:每次添加消息前,可以判断是否需要添加时间 这里比较的是本地时间,实际上应该比较服务器消息时间,我没做而已
            ChatModel lastModel = mList.get(mList.size() - 1);
            long lastTime = lastModel.getMessageTime();
            LogUtils.e("lastTime:" + lastTime);
            //间隔五分钟
            if (Math.abs(lastTime - currentTime) > 5 * 60 * 1000) {
                addTimeItem(currentTime);
            }
        }
        model.setMessageTime(currentTime);
        mList.add(model);
        mChatAdapter.notifyDataSetChanged();
        //滑动到底部
        mChatView.scrollToPosition(mList.size() - 1);
    }
 
 /**
 * 添加图片
 *
 * @param index
 * @param url
 */
private void addImage(int index, String url) {
    ChatModel model = new ChatModel();
    if (index == 0) {
        model.setType(TYPE_LEFT_IMAGE);
    } else {
        model.setType(TYPE_RIGHT_IMAGE);
    }
    model.setImgUrl(url);
    baseAddItem(model);
}

/**
 * 添加图片
 *
 * @param index
 * @param file
 */
private void addImage(int index, File file) {
    ChatModel model = new ChatModel();
    if (index == 0) {
        model.setType(TYPE_LEFT_IMAGE);
    } else {
        model.setType(TYPE_RIGHT_IMAGE);
    }
    model.setLocalFile(file);
    baseAddItem(model);
}

只有每次进来才会调用查询服务器的消息queryMessage(),然后再解析历史记录进行渲染

/**
 * 解析历史记录
 *
 * @param messages
 */
private void parsingListMessage(List<Message> messages) {
    //倒序
    Collections.reverse(messages);
    //遍历
    for (int i = 0; i < messages.size(); i++) {
        Message m = messages.get(i);
        String objectName = m.getObjectName();
    if (objectName.equals(CloudManager.MSG_IMAGE_NAME)) {
            ImageMessage imageMessage = (ImageMessage) m.getContent();
            String url = imageMessage.getRemoteUri().toString();
            if (!TextUtils.isEmpty(url)) {
                LogUtils.i("url:" + url);
                if (m.getSenderUserId().equals(yourUserId)) {
                    addImage(0, url);//另外一个人的
                } else {
                    addImage(1, url);//自己的
                }
            }
        }
        }
    }
}

Service 的逻辑:

//接收消息
CloudManager.getInstance().setOnReceiveMessageListener((message, i) -> {
    parsingImMessage(message);
    return false;
});
   /**
     * 解析消息体
     *
     * @param message
     */
    private void parsingImMessage(Message message) {
        LogUtils.i("message:" + message);
        String objectName = message.getObjectName();
        if (objectName.equals(CloudManager.MSG_IMAGE_NAME)) {
    try {
        ImageMessage imageMessage = (ImageMessage) message.getContent();
        String url = imageMessage.getRemoteUri().toString();
        if (!TextUtils.isEmpty(url)) {
            LogUtils.i("url:" + url);
            MessageEvent event = new MessageEvent(EventManager.FLAG_SEND_IMAGE);
            event.setImgUrl(url);
            event.setUserId(message.getSenderUserId());
            EventManager.post(event);
            pushSystem(message.getSenderUserId(), 1, 0, 0, getString(R.string.text_chat_record_img));
        }
    } catch (Exception e) {
        LogUtils.e("e." + e.toString());
        e.printStackTrace();
    }
    }
    
    

通过在Activity中onMessageEvent处理事件:

case EventManager.FLAG_SEND_IMAGE:
    addImage(0, event.getImgUrl());//别人发过来的
    break;

下面实现图片预览:

使用开源控件photoview

**
 * FileName: ImagePreviewActivity
 * Profile: 图片预览
 */
public class ImagePreviewActivity extends BaseUIActivity implements View.OnClickListener {

    /**
     * 跳转
     * @param mContext
     * @param isUrl
     * @param url
     */
    public static void startActivity(Context mContext, boolean isUrl, String url) {
        Intent intent = new Intent(mContext, ImagePreviewActivity.class);
        intent.putExtra(Constants.INTENT_IMAGE_TYPE, isUrl);
        intent.putExtra(Constants.INTENT_IMAGE_URL, url);
        mContext.startActivity(intent);
    }

    private PhotoView photo_view;
    private ImageView iv_back;
    private TextView tv_download;

    //图片地址
    private String url;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_preview);

        initView();
    }

    private void initView() {
        photo_view = (PhotoView) findViewById(R.id.photo_view);
        iv_back = (ImageView) findViewById(R.id.iv_back);
        tv_download = (TextView)findViewById(R.id.tv_download);

        iv_back.setOnClickListener(this);
        tv_download.setOnClickListener(this);

        Intent intent = getIntent();
        boolean isUrl = intent.getBooleanExtra(Constants.INTENT_IMAGE_TYPE,false);
        url = intent.getStringExtra(Constants.INTENT_IMAGE_URL);

        //图片地址才下载,File代表本次已经存在
        tv_download.setVisibility(isUrl?View.VISIBLE:View.GONE);

        if(isUrl){
            GlideHelper.loadUrl(this,url,photo_view);
        }else{
            GlideHelper.loadFile(this,new File(url),photo_view);
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iv_back:
                finish();
                break;
            case R.id.tv_download:
                Toast.makeText(this, getString(R.string.text_iv_pre_downloading), Toast.LENGTH_SHORT).show();
                GlideHelper.loadUrlToBitmap(this, url, new GlideHelper.OnGlideBitmapResultListener() {
                    @Override
                    public void onResourceReady(Bitmap resource) {
                        if(resource != null){
                            FileHelper.getInstance().saveBitmapToAlbum(ImagePreviewActivity.this,resource);
                        }else{
                            Toast.makeText(ImagePreviewActivity.this, getString(R.string.text_iv_pre_save_fail), Toast.LENGTH_SHORT).show();
                        }
                    }
                });
                break;
        }
    }
}
相关标签: android