融云快速集成Demo+自定義消息+連接+會話界面+會話列表+發送消息+用戶信息提供者

項目總結之即時通訊
融云的服務真是快,有問題提工單,工程師回答速度快,可以很方便解決實際開發中的問題。作為總結,我們還是隨便聊聊融云的使用吧!直接進入正題————>>>
首先去融云開發者平臺注冊、下載SDK、導包、連接、實現會話列表和會話界面這里就簡單說明一下。不懂的可以去之前文章看。本片重點說一下自定義消息和plugin擴展區域自定義。
第一步,使用第三方的東西肯定要去他們的官網注冊一個開發者賬號,步驟很簡單,一步步填寫,下一步就行。注意手機號的填寫,還是要填寫真實的,貌似有條規定,如果手機號為空號可能會導致他們不會給改用戶下的app提供服務,所以為了安全起見還是填寫真實的手機號碼。注冊鏈接地址
第二步:下載SDK,建議SDK別使用當前太低版本、因為有些功能可能不支持。下載SDK時,我們也要把官方提供的demo下載下來,畢竟這是第一手資料,官網提供的demo功能還是比較豐富的,如果應用要求的功能不是很多,demo里面提供的基本功能使應該能滿足的。demo可能是托管在github上的,所以還要有個git賬號。請自行注冊,畢竟開發者還是應該多去上面看看大牛寫的開源東西來學習。
第三步:注冊應用,使用第三方的工具,不注冊怎么用呢?個人中心填寫下應用的基本情況應該沒啥問題了。

簡要的幾個步驟,具體使用可以參照官方提供的幫助文檔,官方文檔地址戳這里

功能介紹

前沿簡介

前奏

使用第三方的庫,首先就需要進行第三方要求的初始化操作,這部分代碼,基本直接copy官網提供的就可以,這樣可以保證準確性。所以這里簡要介紹需要我們處理的幾個點。
1、Manifest.xml文件中:
android:host選項的值全部為自己應用的包名。例如:android:host=”com.dsw.infor”
meta-data標簽中的appkey的值要改為自己應用申請的appkey

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mydemoplugin">
    <permission
        android:name="cn.rongcloud.im.permission.MIPUSH_RECEIVE"
        android:protectionLevel="signature" /> <!-- 發送位置消息,實時位置共享,如果您需要定位相關的功能,可以打開以下注釋 -->
    <permission
        android:name="cn.rongcloud.im.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

    <permission
        android:name="cn.rongcloud.im.push.permission.MESSAGE"
        android:protectionLevel="signature" /> <!-- targetSdkVersion為29時,如果需要后臺定位權限,需要添加 ACCESS_BACKGROUND_LOCATION 權限 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- ?米 配置開始 < -->
    <uses-permission android:name="MediaStore.Images.Media.INTERNAL_CONTENT_URI" />
    <uses-permission android:name="MediaStore.Images.Media.EXTERNAL_CONTENT_URI" /> <!-- ?米 配置結束 < -->
    <!-- GCM 配置開始 < -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- GCM 配置結束 < -->
    <!-- 華為 配置開始 < -->
    <!-- HMS-SDK引導升級HMS功能,訪問OTA服務器需要網絡權限 -->
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- HMS-SDK引導升級HMS功能,保存下載的升級包需要SD卡寫權限 -->
    <uses-permission android:name="cn.rongcloud.im.permission.MIPUSH_RECEIVE" /> <!-- 檢測網絡狀態 -->
    <uses-permission android:name="cn.rongcloud.im.permission.C2D_MESSAGE" /> <!-- 檢測wifi狀態 -->
    <uses-permission android:name="android.permission.INTERNET" /> <!-- 為了獲取用戶手機的IMEI,用來唯一的標識用戶;發送位置及實時位置時需要此權限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 如果是安卓8.0,應用編譯配置的targetSdkVersion>=26,請務必添加以下權限 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 華為 配置結束 < -->
    <!-- MeiZu 配置開始 < -->
    <!-- 兼容 flyme5.0 以下版本,魅族內部集成 pushSDK 必填,不然無法收到 消息 -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <!-- 兼容 flyme3.0 配置權限 -->
    <uses-permission android:name="com.meizu.flyme.push.permission.RECEIVE" /> <!-- MeiZu 配置結束 < -->
    <!-- OPPPO 權限配置 -->
    <uses-permission android:name="cn.rongcloud.im.push.permission.MESSAGE" /> <!-- OPPO 配置結束 -->
    <uses-permission android:name="com.meizu.c2dm.permission.RECEIVE" /> <!-- 為了獲取用戶手機的IMEI,用來唯一的標識用戶;發送位置消息,實時位置共享需要此權限 -->
    <uses-permission android:name="com.coloros.mcs.permission.SEND_MCS_MESSAGE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <uses-permission android:name="android.permission.VIBRATE" />
    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyDemoPlugin">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ConversationActivity"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateHidden|adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data
                    android:host="com.example.mydemoplugin"
                    android:pathPrefix="/conversation/"
                    android:scheme="rong" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ConversationListActivity"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateHidden|adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />

                <data
                    android:host="com.example.mydemoplugin"
                    android:pathPrefix="/conversationlist"
                    android:scheme="rong" />
            </intent-filter>
        </activity>
    </application>

</manifest>

2、在我們的Application中進行初始化,執行RongIM.init(this);
代碼如下:

/**
 * 應用啟動時,判斷用戶是否已接受隱私協議,如果已接受,正常初始化;否則跳轉到隱私授權頁面請求用戶授權。
 */
public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
//        if (!AppContext.isInitialized()) {
//            AppContext.init(getApplicationContext());
//        }
        //用戶已接受隱私協議,進行初始化
        String appKey = "pvxdm17jpws8r";
        //            第一個參數必須傳應用上下文
        RongIM.init(this.getApplicationContext(), appKey);
        //注冊Plugin自定義類型
        registerExtensionPlugin();
        //消息自定義類型
        RongIM.registerMessageType(RedPackageMessage.class);
        RongIM.registerMessageTemplate(new RedPackageItemProvider());
    }

    private void registerExtensionPlugin() {
        List<IExtensionModule> moduleList = RongExtensionManager.getInstance().getExtensionModules();
        IExtensionModule defaultModule = null;
        if (moduleList != null) {
            for (IExtensionModule module : moduleList) {
                if (module instanceof DefaultExtensionModule) {
                    defaultModule = module;
                    break;
                }
            }
            if (defaultModule != null) {
                //移除已注冊的默認模塊,替換成自定義模塊RongExtensionManager.getInstance().unregisterExtensionModule(defaultModule);
                RongExtensionManager.getInstance().unregisterExtensionModule(defaultModule);
                RongExtensionManager.getInstance().registerExtensionModule(new SealExtensionModule());
            }
        }
    }
}

3、初始化的工作完成后,然后我們就在我們成功登陸后,進行服務器的鏈接。此時,我們需要調用我們的后臺來獲取融云認證的token信息。測試階段,我們可以使用api調試,手動生成來用。

RongIM.connect(token, new ConnectCallback() {

                    @Override
                    public void onSuccess(String arg0) {
                        Log.d("RongClound", "RongClound: Tocken Success");
                    }

                    @Override
                    public void onError(ErrorCode arg0) {
                        Log.d("RongClound", "RongClound: Tocken Error,ErrorCode:" + arg0);
                    }

                    @Override
                    public void onTokenIncorrect() {
                        Log.d("RongClound", "RongClound: onTokenIncorrect");
                    }
                });

4.單聊功能
由于IMKit中融云提供的界面都是基于fragment,所以使用也是簡單,我們只需要簡單配置下我們的會話列表界面就可以了,比如:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

布局搞好了,我們要創建一個ConversationActivity來進行顯示。

public class ConversationListActivity extends FragmentActivity {

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

        ConversationListFragment conversationListFragment=new ConversationListFragment();
        // 此處設置 Uri. 通過 appendQueryParameter 去設置所要支持的會話類型. 例如
        // .appendQueryParameter(Conversation.ConversationType.PRIVATE.getName(),"false")
        // 表示支持單聊會話, false 表示不聚合顯示, true 則為聚合顯示
        Uri uri = Uri.parse("rong://" +
                getApplicationContext().getApplicationInfo().packageName).buildUpon()
                .appendPath("conversationlist")
                .appendQueryParameter(Conversation.ConversationType.PRIVATE.getName(), "false") //設置私聊會話是否聚合顯示
                .appendQueryParameter(Conversation.ConversationType.GROUP.getName(), "false")//群組
                .appendQueryParameter(Conversation.ConversationType.PUBLIC_SERVICE.getName(), "false")//公共服務號
                .appendQueryParameter(Conversation.ConversationType.APP_PUBLIC_SERVICE.getName(), "false")//訂閱號
                .appendQueryParameter(Conversation.ConversationType.SYSTEM.getName(), "true")//系統
                .build();

        conversationListFragment.setUri(uri);
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(R.id.container, conversationListFragment);
        transaction.commit();

Activity創建好自然要在Manifest中進行聲明

        <activity
            android:name=".ConversationListActivity"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateHidden|adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />

                <data
                    android:host="com.example.mydemoplugin"
                    android:pathPrefix="/conversationlist"
                    android:scheme="rong" />
            </intent-filter>
        </activity>

回話界面

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
public class ConversationActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_conversation);
        ConversationFragment conversationFragment = new ConversationFragment();
        Intent intent = getIntent(); // 取得從上一個Activity當中傳遞過來的Intent對象
        String targetId = null;
        if (intent != null) {
            targetId = intent.getStringExtra("targetId");
        }
        Uri uri = Uri.parse("rong://" +
                getApplicationContext().getApplicationInfo().packageName).buildUpon()
                .appendPath("conversation").appendPath("private")
                .appendQueryParameter("targetId", targetId)//設置私聊會話是否聚合顯示,targetId:單聊人的id
                .build();

        conversationFragment.setUri(uri);
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(R.id.container, conversationFragment);
        transaction.commit();
    }
}

至此單聊功能就實現了!開始進入正題自定義消息和Plugin擴展。
自定義消息
參考資料:http://www.rongcloud.cn/docs/android.html#新建消息

  1. 自定義消息實體 –RedPackageMessage(一個自定義的紅包消息)
package com.example.mydemoplugin.PhoneInfoProvider;

/**
 * Created by zhangbowen on 6/15/21.
 **/

import android.os.Parcel;
import android.util.Log;

import com.alibaba.fastjson.JSON;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;

import io.rong.common.ParcelUtils;
import io.rong.imlib.MessageTag;
import io.rong.imlib.model.MessageContent;
import io.rong.message.CSSuspendMessage;

/*
 * 注解名:MessageTag ;屬性:value ,flag; value 即 ObjectName 是消息的唯一標識不可以重復,
 * 開發者命名時不能以 RC 開頭,避免和融云內置消息沖突;flag 是用來定義消息的可操作狀態。
 *如下面代碼段,自定義消息名稱 CustomizeMessage ,vaule 是 app:custom ,
 * flag 是 MessageTag.ISCOUNTED | MessageTag.ISPERSISTED 表示消息計數且存庫。
 * app:RedPkgMsg: 這是自定義消息類型的名稱,測試的時候用"app:RedPkgMsg";
 * */
@MessageTag(value = "app:RedPkgMsg", flag = MessageTag.ISCOUNTED | MessageTag.ISPERSISTED)
public class RedPackageMessage extends MessageContent {

    //自定義的屬性
    private String title;
    private String storeName;
    private String desc1;
    private String desc2;

    public RedPackageMessage() {
    }

    public static RedPackageMessage obtain(String title, String storeName, String desc1, String desc2) {
        RedPackageMessage message = new RedPackageMessage();
        message.title = title;
        message.storeName = storeName;
        message.desc1 = desc1;
        message.desc2 = desc2;
        return message;
    }

    /*
     *
     * 實現 encode() 方法,該方法的功能是將消息屬性封裝成 json 串,
     * 再將 json 串轉成 byte 數組,該方法會在發消息時調用,如下面示例代碼:
     * */
    @Override
    public byte[] encode() {
        JSONObject jsonObj = new JSONObject();

        try {
            jsonObj.put("title", this.getTitle());
            jsonObj.put("storeName", this.getStoreName());
            jsonObj.put("desc1", this.getDesc1());
            jsonObj.put("desc2", this.getDesc2());

        } catch (JSONException e) {
            Log.e("JSONException", e.getMessage());
        }

        try {
            return jsonObj.toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /*
     * 覆蓋父類的 MessageContent(byte[] data) 構造方法,該方法將對收到的消息進行解析,
     * 先由 byte 轉成 json 字符串,再將 json 中內容取出賦值給消息屬性。
     * */
    public RedPackageMessage(byte[] data) {
        String jsonStr = null;

        try {
            jsonStr = new String(data, "UTF-8");
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        }

        try {
            JSONObject jsonObj = new JSONObject(jsonStr);

            if (jsonObj.has("title"))
                setTitle(jsonObj.optString("title"));

            if (jsonObj.has("storeName"))
                setStoreName(jsonObj.optString("storeName"));

            if (jsonObj.has("desc1"))
                setDesc1(jsonObj.optString("desc1"));

            if (jsonObj.has("desc2"))
                setDesc2(jsonObj.optString("desc2"));

        } catch (JSONException e) {
            Log.d("JSONException", e.getMessage());
        }
    }

    //給消息賦值。
    public RedPackageMessage(Parcel in) {

        setTitle(ParcelUtils.readFromParcel(in));//該類為工具類,消息屬性
        //這里可繼續增加你消息的屬性
        setStoreName(ParcelUtils.readFromParcel(in));//該類為工具類,消息屬性
        setDesc1(ParcelUtils.readFromParcel(in));//該類為工具類,消息屬性
        setDesc2(ParcelUtils.readFromParcel(in));//該類為工具類,消息屬性
    }

    /**
     * 讀取接口,目的是要從Parcel中構造一個實現了Parcelable的類的實例處理。
     */
    public static final Creator<RedPackageMessage> CREATOR = new Creator<RedPackageMessage>() {

        @Override
        public RedPackageMessage createFromParcel(Parcel source) {
            return new RedPackageMessage(source);
        }

        @Override
        public RedPackageMessage[] newArray(int size) {
            return new RedPackageMessage[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    /**
     * 將類的數據寫入外部提供的 Parcel 中。
     *
     * @param dest  對象被寫入的 Parcel。
     * @param flags 對象如何被寫入的附加標志。
     */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        ParcelUtils.writeToParcel(dest, getTitle());
        ParcelUtils.writeToParcel(dest, getStoreName());
        ParcelUtils.writeToParcel(dest, getDesc1());
        ParcelUtils.writeToParcel(dest, getDesc2());
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getStoreName() {
        return storeName;
    }

    public void setStoreName(String storeName) {
        this.storeName = storeName;
    }

    public String getDesc1() {
        return desc1;
    }

    public void setDesc1(String desc1) {
        this.desc1 = desc1;
    }

    public String getDesc2() {
        return desc2;
    }

    public void setDesc2(String desc2) {
        this.desc2 = desc2;
    }
}

2.自定義消息提供者

package com.example.mydemoplugin.PhoneInfoProvider;

import android.content.ClipboardManager;
import android.content.Context;
import android.text.Spannable;
import android.text.SpannableString;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.example.mydemoplugin.R;

import io.rong.imkit.RongIM;
import io.rong.imkit.emoticon.AndroidEmoji;
import io.rong.imkit.model.ProviderTag;
import io.rong.imkit.model.UIMessage;
import io.rong.imkit.utilities.OptionsPopupDialog;
import io.rong.imkit.widget.provider.IContainerItemProvider;
import io.rong.imlib.RongIMClient;
import io.rong.imlib.model.Message;

/**
 * Created by zhangbowen on 6/15/21.PhoneInfo的布局
 * desc新建一個消息類繼承 IContainerItemProvider.MessageProvider 類,實現對應接口方法,
 * 1.注意開頭的注解!
 * 2.注意泛型!
 */
@ProviderTag(
        messageContent = RedPackageMessage.class,
        showReadState = true
)
public class RedPackageItemProvider extends IContainerItemProvider.MessageProvider<RedPackageMessage> {

    public RedPackageItemProvider() {
    }

    @Override
    public View newView(Context context, ViewGroup viewGroup) {
        //這就是展示在會話界面的自定義的消息的布局
        View view = LayoutInflater.from(context).inflate(R.layout.item_redpackage_message, null);
        ViewHolder holder = new ViewHolder();
        holder.ll_msg = (FrameLayout) view.findViewById(R.id.ll_msg);
        holder.tvTitle = (TextView) view.findViewById(R.id.tv_title);
        holder.tvStoreName = (TextView) view.findViewById(R.id.tv_store_name);
        holder.tvDesc1 = (TextView) view.findViewById(R.id.tv_desc1);
        holder.tvDesc2 = (TextView) view.findViewById(R.id.tv_desc2);
        view.setTag(holder);
        return view;
    }

    @Override
    public void bindView(View view, int i, RedPackageMessage redPackageMessage, UIMessage message) {

        //根據需求,適配數據
        ViewHolder holder = (ViewHolder) view.getTag();
        if (message.getMessageDirection() == Message.MessageDirection.SEND) {//消息方向,自己發送的
//            holder.ll_msg.setBackgroundResource(io.rong.imkit.R.drawable.rc_ic_bubble_right);
        } else {
//            holder.ll_msg.setBackgroundResource(io.rong.imkit.R.drawable.rc_ic_bubble_left);
        }
//        AndroidEmoji.ensure((Spannable) holder.message.getText());//顯示消息中的 Emoji 表情。
        holder.tvTitle.setText(redPackageMessage.getTitle());
        holder.tvStoreName.setText(redPackageMessage.getStoreName());
        holder.tvDesc1.setText(redPackageMessage.getDesc1());
        holder.tvDesc2.setText(redPackageMessage.getDesc2());
    }

    @Override
    public Spannable getContentSummary(RedPackageMessage redPackageMessage) {
        return new SpannableString(redPackageMessage.getDesc1());
    }

    @Override
    public void onItemClick(View view, int i, RedPackageMessage redPackageMessage, UIMessage uiMessage) {

    }

    @Override
    public void onItemLongClick(View view, int i, RedPackageMessage redPackageMessage, UIMessage uiMessage) {
        //實現長按刪除等功能,咱們直接復制融云其他provider的實現
        String[] items1;//復制,刪除
        items1 = new String[]{view.getContext().getResources().getString(io.rong.imkit.R.string.rc_dialog_item_message_copy), view.getContext().getResources().getString(io.rong.imkit.R.string.rc_dialog_item_message_delete)};

        OptionsPopupDialog.newInstance(view.getContext(), items1).setOptionsPopupDialogListener(new OptionsPopupDialog.OnOptionsItemClickedListener() {
            public void onOptionsItemClicked(int which) {
//                Log.e("實現長按刪除等功能",uiMessage.getMessage().getMessageId()+"---"+redPackageMessage.describeContents()+"-----"+uiMessage.getMessage());
                //長安復制暫時沒有實現
                if (which == 0) {
                    ClipboardManager clipboard = (ClipboardManager) view.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
//                    clipboard.setText(redPackageMessage.encode());//這里是自定義消息的消息屬性
                } else if (which == 1) {
                    RongIM.getInstance().deleteMessages(new int[]{uiMessage.getMessage().getMessageId()}, (RongIMClient.ResultCallback) null);
                }
            }
        }).show();

    }

    private static class ViewHolder {
        TextView tvTitle, tvStoreName, tvDesc1, tvDesc2;
        FrameLayout ll_msg;
    }
}

3.注意自定義消息的布局:(整體布局外面再嵌套一層)

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll_msg"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:layout_width="220dp"
        android:layout_height="100dp"
        android:background="#eca24f">

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="23dp"
            android:layout_marginTop="8dp"
            android:text="標題"
            android:textColor="#333fff"
            android:textSize="12dp" />

        <TextView
            android:id="@+id/tv_store_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="70dp"
            android:layout_marginTop="36dp"
            android:singleLine="true"
            android:text="店名店名店名店名店名店名店名店名店名"
            android:textColor="@color/white"
            android:textSize="15dp" />

        <TextView
            android:id="@+id/tv_desc1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="70dp"
            android:layout_marginTop="55dp"
            android:singleLine="true"
            android:text="送你一個現金紅包"
            android:textColor="@color/white"
            android:textSize="12dp" />

        <TextView
            android:id="@+id/tv_desc2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="70dp"
            android:layout_marginTop="73dp"
            android:singleLine="true"
            android:text="點擊領取紅包"
            android:textColor="@color/white"
            android:textSize="12dp" />

    </RelativeLayout>
</FrameLayout>
WeChatd051bc561c017d0e6e02e2410ee9c7aa.png

4.注冊消息類型以及消息提供者
RongIM.init(this);
//注意,要在初始化之后注冊
RongIM.registerMessageType(RedPackageMessage.class);
RongIM.registerMessageTemplate(new RedPackageItemProvider());
5.官網測試發消息


WeChatb0b6e1c0d1863f8cdc08bfcd9bd2ad24.png

6.自定義紅包Plugin

/**
 * Created by zhangbowen on 6/15/21.
 * 自定義紅包Plugin
 **/
public class MyPlugin implements IPluginModule {
    @Override
    public Drawable obtainDrawable(Context context) {
        return ContextCompat.getDrawable(context, io.rong.imkit.R.drawable.rc_cs_evaluate_selector);
    }

    @Override
    public String obtainTitle(Context context) {
        return "紅包";
    }

    @Override
    public void onClick(Fragment fragment, RongExtension rongExtension) {
        Log.e("發紅包啦!!!", rongExtension.getTargetId());
        RedPackageMessage redPackageMessage = RedPackageMessage.obtain("測試" + new Random().nextInt(1000), "商店名稱" + new Random().nextInt(1000), "描述" + new Random().nextInt(1000), "描述" + new Random().nextInt(1000));
        RongIM.getInstance().sendMessage(Conversation.ConversationType.PRIVATE, rongExtension.getTargetId(), redPackageMessage, "測試一下pushContent" + new Random().nextInt(100), "測試一下pushData" + new Random().nextInt(100)
                , new IRongCallback.ISendMediaMessageCallback() {
                    @Override
                    public void onAttached(Message message) {

                    }

                    @Override
                    public void onSuccess(Message message) {

                    }

                    @Override
                    public void onError(Message message, RongIMClient.ErrorCode errorCode) {

                    }

                    @Override
                    public void onProgress(Message message, int i) {

                    }

                    @Override
                    public void onCanceled(Message message) {

                    }
                });
    }

    @Override
    public void onActivityResult(int i, int i1, Intent intent) {
        Log.e("發紅包啦!!!", "onActivityResult");
    }
}
/**
 * Created by zhangbowen on 6/15/21.
 * Plugin自定義類型
 **/
public class SealExtensionModule extends DefaultExtensionModule {
    @Override
    public List<IPluginModule> getPluginModules(Conversation.ConversationType conversationType) {
        List<IPluginModule> pluginModuleList = new ArrayList<>();
        IPluginModule image = new ImagePlugin();
        IPluginModule location = new DefaultLocationPlugin();
        //        IPluginModule audio = new AudioPlugin();
        //        IPluginModule video = new VideoPlugin();
        IPluginModule file = new FilePlugin();
        IPluginModule myPlugin = new MyPlugin();

        if (conversationType.equals(Conversation.ConversationType.GROUP) ||
                conversationType.equals(Conversation.ConversationType.DISCUSSION) ||
                conversationType.equals(Conversation.ConversationType.PRIVATE)) {
            pluginModuleList.add(image);
            pluginModuleList.add(location);
            //            pluginModuleList.add(audio);
            //            pluginModuleList.add(video);
            pluginModuleList.add(file);
            pluginModuleList.add(myPlugin);
        } else {
            pluginModuleList.add(image);
        }

        return pluginModuleList;
    }

    @Override
    public List<IEmoticonTab> getEmoticonTabs() {
        return super.getEmoticonTabs();
    }
}

7.將自定義好的Plugin重新注冊(在init初始化之后注冊)

    private void registerExtensionPlugin() {
        List<IExtensionModule> moduleList = RongExtensionManager.getInstance().getExtensionModules();
        IExtensionModule defaultModule = null;
        if (moduleList != null) {
            for (IExtensionModule module : moduleList) {
                if (module instanceof DefaultExtensionModule) {
                    defaultModule = module;
                    break;
                }
            }
            if (defaultModule != null) {
                //移除已注冊的默認模塊,替換成自定義模塊RongExtensionManager.getInstance().unregisterExtensionModule(defaultModule);
                RongExtensionManager.getInstance().unregisterExtensionModule(defaultModule);
                RongExtensionManager.getInstance().registerExtensionModule(new SealExtensionModule());
            }
        }
    }

以上就是關于融云在項目中的使用,融云提供很多功能,希望以后有機會再深入研究吧!
簡單demo下載地址

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 偶然發現,用過一些,分享給大家 { "XcodeChaJian": [ { "Dname":"...
    MonkeyHan閱讀 6,553評論 0 4
  • 表情是什么,我認為表情就是表現出來的情緒。表情可以傳達很多信息。高興了當然就笑了,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,771評論 2 7
  • 16宿命:用概率思維提高你的勝算 以前的我是風險厭惡者,不喜歡去冒險,但是人生放棄了冒險,也就放棄了無數的可能。 ...
    yichen大刀閱讀 6,083評論 0 4