基于环信的仿QQ即时通讯的简单实现
代碼地址如下:
http://www.demodashi.com/demo/11645.html
我的博客地址
之前一直想實現聊天的功能,但是感覺有點困難,今天看了環信的API,就利用下午的時間動手試了試,然后做了一個小Demo。
因為沒有刻意去做聊天軟件,花的時間也不多,然后界面就很簡單,都是一些基本知識,如果覺得功能簡單,可以自行添加,我這就不多介紹了。
照例先來一波動態演示:
功能很簡單,注冊用戶 --> 用戶登錄 --> 選擇聊天對象 --> 開始聊天
使用到的知識點:
依賴的庫
compile 'com.android.support:appcompat-v7:24.2.1' compile 'com.android.support:cardview-v7:24.1.1' compile 'com.android.support:recyclerview-v7:24.0.0'1、聊天頁面
首先是看了郭神的《第二行代碼》做了聊天界面,用的是RecyclerView
#### a. 消息類的封裝 ####
public class MSG {public static final int TYPE_RECEIVED = 0;//消息的類型:接收public static final int TYPE_SEND = 1; //消息的類型:發送private String content;//消息的內容private int type; //消息的類型public MSG(String content, int type) {this.content = content;this.type = type;}public String getContent() {return content;}public int getType() {return type;} }#### b. RecyclerView子項的布局 ####
<LinearLayoutandroid:id="@+id/ll_msg_left"android:layout_width="wrap_content"android:layout_height="wrap_content"<!-- 設置點擊效果為水波紋(5.0以上) -->android:background="?android:attr/selectableItemBackground"android:clickable="true"android:focusable="true"android:orientation="horizontal"android:padding="2dp"><android.support.v7.widget.CardViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"app:cardCornerRadius="20dp"app:cardPreventCornerOverlap="false"app:cardUseCompatPadding="true"><ImageViewandroid:layout_width="50dp"android:layout_height="50dp"android:scaleType="centerCrop"android:src="@mipmap/man" /></android.support.v7.widget.CardView><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/message_left"android:orientation="horizontal"><TextViewandroid:id="@+id/tv_msg_left"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_margin="10dp"android:textColor="#fff" /></LinearLayout></LinearLayout>這是左邊的部分,至于右邊應該也就簡單了。我用CardView把ImageView包裹起來,這樣比較好看。效果如下:
#### c. RecyclerView適配器 ####
public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.MyViewHolder> {private List<MSG> mMsgList;public MsgAdapter(List<MSG> mMsgList) {this.mMsgList = mMsgList;}@Overridepublic MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View view = View.inflate(parent.getContext(), R.layout.item_msg, null);MyViewHolder holder = new MyViewHolder(view);return holder;}@Overridepublic void onBindViewHolder(MyViewHolder holder, int position) {MSG msg = mMsgList.get(position);if (msg.getType() == MSG.TYPE_RECEIVED){//如果是收到的消息,顯示左邊布局,隱藏右邊布局holder.llLeft.setVisibility(View.VISIBLE);holder.llRight.setVisibility(View.GONE);holder.tv_Left.setText(msg.getContent());} else if (msg.getType() == MSG.TYPE_SEND){//如果是發送的消息,顯示右邊布局,隱藏左邊布局holder.llLeft.setVisibility(View.GONE);holder.llRight.setVisibility(View.VISIBLE);holder.tv_Right.setText(msg.getContent());}}@Overridepublic int getItemCount() {return mMsgList.size();}static class MyViewHolder extends RecyclerView.ViewHolder{LinearLayout llLeft;LinearLayout llRight;TextView tv_Left;TextView tv_Right;public MyViewHolder(View itemView) {super(itemView);llLeft = (LinearLayout) itemView.findViewById(R.id.ll_msg_left);llRight = (LinearLayout) itemView.findViewById(R.id.ll_msg_right);tv_Left = (TextView) itemView.findViewById(R.id.tv_msg_left);tv_Right = (TextView) itemView.findViewById(R.id.tv_msg_right);}} }這部分應該也沒什么問題,就是適配器的創建,我之前的文章也講過 傳送門:簡單粗暴----RecyclerView
#### d. RecyclerView初始化 ####
就是一些基本的初始化,我就不贅述了,講一下添加數據的細節處理
btSend.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String content = etInput.getText().toString().trim();if (!TextUtils.isEmpty(content)){...//環信部分的發送消息MSG msg = new MSG(content, MSG.TYPE_SEND);mList.add(msg);//當有新消息時,刷新RecyclerView中的顯示mAdapter.notifyItemInserted(mList.size() - 1);//將RecyclerView定位到最后一行mRecyclerView.scrollToPosition(mList.size() - 1);etInput.setText("");}}});至此界面已經結束了,接下來就是數據的讀取
2. 環信API的簡單應用
官網有詳細的API介紹 環信及時通訊V3.0,我這里就簡單介紹如何簡單集成
#### a. 環信開發賬號的注冊 ####
環信官網
創建應用得到Appkey后面要用
#### b. SDK導入 ####
你可以直接下載然后拷貝工程的libs目錄下
Android Studio可以直接添加依賴
將以下代碼放到項目根目錄的build.gradle文件里
repositories {maven { url "https://raw.githubusercontent.com/HyphenateInc/Hyphenate-SDK-Android/master/repository" } }在你的module的build.gradle里加入以下代碼
android {//use legacy for android 6.0useLibrary 'org.apache.http.legacy' } dependencies {compile 'com.android.support:appcompat-v7:23.4.0'//Optional compile for GCM (Google Cloud Messaging).compile 'com.google.android.gms:play-services-gcm:9.4.0'compile 'com.hyphenate:hyphenate-sdk:3.2.3' }如果想使用不包含音視頻通話的sdk,用compile 'com.hyphenate:hyphenate-sdk-lite:3.2.3'
#### c. 清單文件配置 ####
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"package="Your Package"android:versionCode="100"android:versionName="1.0.0"><!-- Required --><uses-permission android:name="android.permission.VIBRATE" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.GET_TASKS" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /><uses-permission android:name="android.permission.WAKE_LOCK" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /><applicationandroid:icon="@drawable/ic_launcher"android:label="@string/app_name"android:name="Your Application"><!-- 設置環信應用的AppKey --><meta-data android:name="EASEMOB_APPKEY" android:value="Your AppKey" /><!-- 聲明SDK所需的service SDK核心功能--><service android:name="com.hyphenate.chat.EMChatService" android:exported="true"/><service android:name="com.hyphenate.chat.EMJobService"android:permission="android.permission.BIND_JOB_SERVICE"android:exported="true"/><!-- 聲明SDK所需的receiver --><receiver android:name="com.hyphenate.chat.EMMonitorReceiver"><intent-filter><action android:name="android.intent.action.PACKAGE_REMOVED"/><data android:scheme="package"/></intent-filter><!-- 可選filter --><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"/><action android:name="android.intent.action.USER_PRESENT" /></intent-filter></receiver></application> </manifest>APP打包混淆
-keep class com.hyphenate.** {*;} -dontwarn com.hyphenate.**#### d. 初始化SDK ####
在自定義Application的onCreate中初始化
public class MyApplication extends Application {private Context appContext;@Overridepublic void onCreate() {super.onCreate();EMOptions options = new EMOptions();options.setAcceptInvitationAlways(false);appContext = this;int pid = android.os.Process.myPid();String processAppName = getAppName(pid);// 如果APP啟用了遠程的service,此application:onCreate會被調用2次// 為了防止環信SDK被初始化2次,加此判斷會保證SDK被初始化1次// 默認的APP會在以包名為默認的process name下運行,如果查到的process name不是APP的process name就立即返回if (processAppName == null || !processAppName.equalsIgnoreCase(appContext.getPackageName())) {Log.e("--->", "enter the service process!");// 則此application::onCreate 是被service 調用的,直接返回return;}//初始化EMClient.getInstance().init(getApplicationContext(), options);//在做打包混淆時,關閉debug模式,避免消耗不必要的資源EMClient.getInstance().setDebugMode(true);}private String getAppName(int pID) {String processName = null;ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);List l = am.getRunningAppProcesses();Iterator i = l.iterator();PackageManager pm = this.getPackageManager();while (i.hasNext()) {ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo) (i.next());try {if (info.pid == pID) {processName = info.processName;return processName;}} catch (Exception e) {// Log.d("Process", "Error>> :"+ e.toString());}}return processName;} }#### e. 注冊和登陸 ####
注冊要在子線程中執行
//注冊失敗會拋出HyphenateException EMClient.getInstance().createAccount(username, pwd);//同步方法EMClient.getInstance().login(userName,password,new EMCallBack() {//回調@Overridepublic void onSuccess() {EMClient.getInstance().groupManager().loadAllGroups();EMClient.getInstance().chatManager().loadAllConversations();Log.d("main", "登錄聊天服務器成功!"); }@Overridepublic void onProgress(int progress, String status) {}@Overridepublic void onError(int code, String message) {Log.d("main", "登錄聊天服務器失敗!");} });#### f. 發送消息 ####
//創建一條文本消息,content為消息文字內容,toChatUsername為對方用戶或者群聊的id,后文皆是如此 EMMessage message = EMMessage.createTxtSendMessage(content, toChatUsername); //發送消息 EMClient.getInstance().chatManager().sendMessage(message);#### g. 接收消息 ####
msgListener = new EMMessageListener() {@Overridepublic void onMessageReceived(List<EMMessage> messages) {//收到消息String result = messages.get(0).getBody().toString();String msgReceived = result.substring(5, result.length() - 1);Log.i(TAG, "onMessageReceived: " + msgReceived);final MSG msg = new MSG(msgReceived, MSG.TYPE_RECEIVED);runOnUiThread(new Runnable() {@Overridepublic void run() {mList.add(msg);mAdapter.notifyDataSetChanged();mRecyclerView.scrollToPosition(mList.size() - 1);}});}@Overridepublic void onCmdMessageReceived(List<EMMessage> messages) {//收到透傳消息}@Overridepublic void onMessageRead(List<EMMessage> list) {}@Overridepublic void onMessageDelivered(List<EMMessage> list) {}@Overridepublic void onMessageChanged(EMMessage message, Object change) {//消息狀態變動}};接收消息的監聽器分別需要在OnResume()和OnDestory()方法中注冊和取消注冊
EMClient.getInstance().chatManager().addMessageListener(msgListener);//注冊EMClient.getInstance().chatManager().removeMessageListener(msgListener);//取消注冊需要注意的是,當接收到消息,需要在主線程中更新適配器,否則會不能及時刷新出來
項目文件截圖:
到此,一個簡單的及時聊天Demo已經完成,功能很簡單,如果需要添加額外功能的話,可以自行參考官網,官網給出的教程還是很不錯的!
最后希望大家能多多支持我,需要你們的支持喜歡!!
基于環信的仿QQ即時通訊的簡單實現
代碼地址如下:
http://www.demodashi.com/demo/11645.html
注:本文著作權歸作者,由demo大師代發,拒絕轉載,轉載需要作者授權
總結
以上是生活随笔為你收集整理的基于环信的仿QQ即时通讯的简单实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 验证Node和npm是否安装成功
- 下一篇: 电动垂直起降飞机已经完成测试,就差一张飞