当前位置: 首页 > 工具软件 > iMall > 使用案例 >

基于Mars的im实战

仲霍英
2023-12-01

im采用的是Mars框架,这一篇是关于发送消息模块。该文是建立在上一篇关于Mars搭建的基础上。也就是说当前默认你的mars环境已经搭建完成。

第一步:在Application初始化Mars项目

//APP的属性类 包括账号类和设备类
public static AppLogic.AccountInfo accountInfo = new AppLogic.AccountInfo(
        new Random(System.currentTimeMillis() / 1000).nextInt(), "anonymous");
 
//启动mars服务
MarsServiceNative.setProfileFactory(new MarsServiceProfileFactory() {
    @Override
    public MarsServiceProfile createMarsServiceProfile() {
        return new DebugMarsServiceProfile(){
            @Override
            public String longLinkHost() {
                return "marsopen.cn";
            }
        };
    }
});

//初始化mars服务
MarsServiceProxy.init(this, getMainLooper(), null);
//mars账号设置
MarsServiceProxy.inst.accountInfo = accountInfo;
/**
 * Created by malei on 2018/4/16.
 */

public class MyApplication extends Application {

    private static final String TAG = "Mars.SampleApplication";

    private static Context context;

    //APP的属性类 包括账号类和设备类
    public static AppLogic.AccountInfo accountInfo = new AppLogic.AccountInfo(
            new Random(System.currentTimeMillis() / 1000).nextInt(), "anonymous");

    public static volatile boolean hasSetUserName = false;

    @Override
    public void onCreate() {
        super.onCreate();
        context = this;

        System.loadLibrary("stlport_shared");
        System.loadLibrary("marsxlog");
        openXlog();

        //启动mars服务
        MarsServiceNative.setProfileFactory(new MarsServiceProfileFactory() {
            @Override
            public MarsServiceProfile createMarsServiceProfile() {
                return new DebugMarsServiceProfile(){
                    @Override
                    public String longLinkHost() {
                        return "marsopen.cn";
                    }
                };
            }
        });

        //初始化mars服务
        MarsServiceProxy.init(this, getMainLooper(), null);
        //mars账号设置
        MarsServiceProxy.inst.accountInfo = accountInfo;

        // Auto bind all activity event
        ActivityEvent.bind(getApplicationContext());

        Log.i(TAG, "application started");

        CustomActivityOnCrash.install(this);
    }

    @Override
    public void onTerminate() {
        Log.i(TAG, "application terminated");

        super.onTerminate();

        Log.appenderClose();

    }

    public static  void openXlog() {

        int pid = android.os.Process.myPid();
        String processName = null;
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo appProcess : am.getRunningAppProcesses()) {
            if (appProcess.pid == pid) {
                processName = appProcess.processName;
                break;
            }
        }

        if (processName == null) {
            return;
        }

        final String SDCARD = Environment.getExternalStorageDirectory().getAbsolutePath();
        final String logPath = SDCARD + "/marssample/log";

        String logFileName = processName.indexOf(":") == -1 ? "MarsSample" : ("MarsSample_" + processName.substring(processName.indexOf(":") + 1));

        if (BuildConfig.DEBUG) {
            Xlog.appenderOpen(Xlog.LEVEL_VERBOSE, Xlog.AppednerModeAsync, "", logPath, logFileName, "");
            Xlog.setConsoleLogOpen(true);
        } else {
            Xlog.appenderOpen(Xlog.LEVEL_INFO, Xlog.AppednerModeAsync, "", logPath, logFileName, "");
            Xlog.setConsoleLogOpen(false);
        }
        Log.setLogImp(new Xlog());
    }

    public static Context getContext() {
        return context;
    }

第二步:创建聊天界面ChatActivity.class(我们先做发消息处理)

发送消息使用的工具类是:MarsServiceProxy,方法是send()。send()方法传人的参数是MarsTaskWrapper接口,所以我们需要实现该接口。

 - onPreEncode () : 发送之前的拦截

 - onPostDecode(): 发送完成后的回调,消息已经到达对方

 - onTaskEnd() : 发送完成后的回调,消息已经到达对方

TextMessageTask类为MarsTaskWrapper接口的实现。

 
/**
 * Created by malei on 2018/4/17.
 * 处理发送的消息
 */
@TaskProperty(
        host = "marsopen.cn",
        path = "/mars/sendmessage",
        cmdID = Main.CMD_ID_SEND_MESSAGE,
        longChannelSupport = true,
        shortChannelSupport = false
)
public class TextMessageTask extends NanoMarsTaskWrapper<Chat.SendMessageRequest, Chat.SendMessageResponse> {

    private Runnable mOnOk;
    private Runnable mOnError;
    private Runnable mCallback;

    private Handler uiHandler = new Handler(Looper.getMainLooper()); //创建主线程的handler

    /**
     *
     * @param topicName : 聊天的频道,两个人聊天的时候,要保证topicName 一致
     * @param text
     */
    public TextMessageTask(String topicName, String text) {
        super(new Chat.SendMessageRequest(), new Chat.SendMessageResponse());

        request.accessToken = "test_token";
        request.from = MyApplication.accountInfo.userName;
        request.to = "all";
        request.text = text;
        request.topic = topicName;
    }

    /**
     * 发送之前的拦截
     * @param request
     */
    @Override
    public void onPreEncode(Chat.SendMessageRequest request) {
        Log.i("TAG",request.text);
    }

    /**
     * 发送完成后的回调
     * @param response
     */
    @Override
    public void onPostDecode(Chat.SendMessageResponse response) {
        if (response.errCode == Chat.SendMessageResponse.ERR_OK) {
            mCallback = mOnOk;
        } else {
            mCallback = mOnError;
        }
    }

    /**
     * 发送完成后的回调,消息已经发送给对方了
     * @param errType
     * @param errCode
     */
    @Override
    public void onTaskEnd(int errType, int errCode) {
        if (mCallback == null) {
            mCallback = mOnError;
        }
        uiHandler.post(mCallback);
    }

    public TextMessageTask onOk(Runnable onOk){
        this.mOnOk = onOk;
        return this;
    }

    public TextMessageTask onError(Runnable onError){
        this.mOnError = onError;
        return this;
    }
}

要完成这个类的所有功能还需要,mars给我们提供的两个类Main.class和Chat.class。这两个类直接从demo中就可以获取,这里就不提供了。

第二部分:接收消息的监听

第一步:首先我们需要初始化接收消息的类

private void initMarsPullChat() {
    //接收新消息的时候使用
    final MainService mainService = new MainService();
    MarsServiceProxy.setOnPushMessageListener(BaseConstants.CGIHISTORY_CMDID, mainService);
    MarsServiceProxy.setOnPushMessageListener(BaseConstants.CONNSTATUS_CMDID, mainService);
    MarsServiceProxy.setOnPushMessageListener(BaseConstants.FLOW_CMDID, mainService);
    MarsServiceProxy.setOnPushMessageListener(BaseConstants.PUSHMSG_CMDID, mainService);
    MarsServiceProxy.setOnPushMessageListener(BaseConstants.SDTRESULT_CMDID, mainService);
}
/**
 * Created by caoshaokun on 16/12/20.
 */
public class MainService implements PushMessageHandler {

    public static String TAG = "Mars.Sample.MainService";

    private Thread recvThread;

    private LinkedBlockingQueue<PushMessage> pushMessages = new LinkedBlockingQueue<>();

    private BusinessHandler[] handlers = new BusinessHandler[] {
        new MessageHandler(),
        new StatisticHandler()
    };

    public MainService() {
        this.start();
    }

    public void start() {
        if (recvThread == null) {
            recvThread = new Thread(pushReceiver, "PUSH-RECEIVER");

            recvThread.start();
        }
    }

    private final Runnable pushReceiver = new Runnable() {
        @Override
        public void run() {
            while (true) {
                try {
                    PushMessage pushMessage = pushMessages.take();
                    if (pushMessage != null) {
                        for (BusinessHandler handler : handlers) {
                            if (handler.handleRecvMessage(pushMessage)) {
                                break;
                            }
                        }
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e1) {
                        //
                    }
                }
            }
        }
    };

    @Override
    public void process(PushMessage message) {
        pushMessages.offer(message);
    }
}

第二步:创建ChatDataCore类,作为消息的接收者。接收消息是通过广播获取,然后通过观察者模式,通知给被观察者ui界面

/**
 * Created by malei on 2018/4/23.
 * 接收消息监听者类
 */

public class ChatDataCore extends Observable {

    private BroadcastReceiver receiver = new RecvMessageReceiver();
    private static ChatDataCore inst = new ChatDataCore();

    public ChatDataCore() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Constants.PUSHACTION);
        MyApplication.getContext().registerReceiver(receiver, intentFilter);
    }

    public static ChatDataCore getInstance() {
        return inst;
    }

    /**
     * 发送消息和接收消息,都会触发该广播
     */
    private class RecvMessageReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent != null && intent.getAction().equals(Constants.PUSHACTION)){
                String topic = intent.getStringExtra("msgtopic");
                String from = intent.getStringExtra("msgfrom");
                String text = intent.getStringExtra("msgcontent");
                ChatActivity.recMsg = text;
                //这两个方法是通知观察者类,数据已经修改
                setChanged();
                notifyObservers();
            }
        }
    }
}

该类继承了Observable,也就成了被观察者。

第三步:让我们的ChatActivity成为接收消息的观察者,通过继承Observer。

/**
 * Created by malei on 2018/4/16.
 * 观察者模式设计
 */
public class ChatActivity extends Activity implements Observer {

    private TextView textView;
    private EditText editText;
    private Button btnSend;
    private String mTopicName = "0" ;  //聊天频道
    public static String recMsg = "";

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_chat);

        //接收消息的监听 成为观察者
        ChatDataCore.getInstance().addObserver(this);

        textView = (TextView)this.findViewById(R.id.textView);
        editText = (EditText)this.findViewById(R.id.editText);
        btnSend = (Button)this.findViewById(R.id.btn);
        btnSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onClickBtnSend();
            }
        });
    }

    private void onClickBtnSend() {
        MyApplication.accountInfo.userName = "malei";
        MarsServiceProxy.send(new TextMessageTask("0",editText.getText().toString())
                        .onOk(new Runnable() {
                            @Override
                            public void run() {
                                Log.i("TAG","onOk");
                            }
                        }).onError(new Runnable() {
                                    @Override
                                    public void run() {
                                        Log.i("TAG","onError");
                                    }
                                }));
    }

    @Override
    public void update(Observable o, Object arg) {
        textView.setText(recMsg);
    }
}
这样,一个最简单的im项目就搭建完成了!
 类似资料: