這篇要來介紹的是 如何在Android使用SignalR完成簡易聊天室
我們要完成上圖畫面
Server 端的實作可以參考我的這篇文章
MVC - 使用SignalR完成簡易聊天室
1.Add SignalR Lib
別懷疑!微軟沒有上傳SignalR的Maven位置
原始碼請至github下載(有點雷.趕時間別去踩)
或是你可以跟我一樣來這裡直接下載jar檔引用
除了要引用signalr-client-sdk還有Gson也要
Manifest記得要加上網路權限
<uses-permission android:name="android.permission.INTERNET"/>
2.Layout
兩個檔案,主畫面與listview的item
先看activity_main的layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
tools:listitem="@layout/item"
android:id="@+id/chatLv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:divider="#ddd"
android:dividerHeight="1dp"
/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginBottom="2dp"
android:layout_marginTop="2dp"
android:background="#000" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="horizontal"
android:padding="5dp">
<EditText
android:id="@+id/messageEt"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="5dp"
/>
<Button
android:id="@+id/sendBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="SEND"
/>
</LinearLayout>
</LinearLayout>
item的layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:padding="5dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/nameTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dp"
android:text="Name"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":"
/>
<TextView
android:id="@+id/messageTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dp"
android:text="Message"
/>
</LinearLayout>
2.Java Code
這邊有三個檔案,稍微解釋一下:
MainActivity(主畫面)
ChatAdapter(ListView Adapter)
ChatData(資料容器)
先說MainActivity,裡面的四個常數的意義
HUB_URL:就是你signalR的DomainName+/signalr
HUB_NAME:Hub檔案名稱
HUB_EVENT_NAME:Hub觸發的事件名稱
HUB_METHOD_NAME:Call的method名稱
下面這張圖可以清楚對照,如果不知道藍框裡面是什麼東西
請先看這篇
public class MainActivity extends Activity {
private static final String HUB_URL = "[你的url]/signalr";
private static final String HUB_NAME = "你的Hub name";
private static final String HUB_EVENT_NAME = "你的事件名稱";
private static final String HUB_METHOD_NAME = "你的Call method name";
private SignalRFuture<Void> mSignalRFuture;
private HubProxy mHub;
private String mName;
private ChatAdapter mChatAdapter;
private ListView mChatLv;
private EditText mMessageEt;
private Button mSendBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mChatLv = (ListView)findViewById(R.id.chatLv);
mMessageEt = (EditText)findViewById(R.id.messageEt);
mSendBtn = (Button)findViewById(R.id.sendBtn);
mName = "Android-"+System.currentTimeMillis();
mChatAdapter = new ChatAdapter(this,0,new ArrayList<ChatData>(),mName);
mChatLv.setAdapter(mChatAdapter);
mSendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
String message = mMessageEt.getText().toString();
mHub.invoke(HUB_METHOD_NAME, mName, message).get();
mMessageEt.setText("");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
});
HubConnection connection = new HubConnection(HUB_URL);
mHub = connection.createHubProxy(HUB_NAME);
mSignalRFuture = connection.start(new ServerSentEventsTransport(connection.getLogger()));
//可以理解為訊息or事件監聽器
mHub.on(HUB_EVENT_NAME, new SubscriptionHandler2<String, String>() {
@Override
public void run(String name,String message) {
//使用AsyncTask來更新畫面
new AsyncTask<String,Void,ChatData>(){
@Override
protected ChatData doInBackground(String... param) {
ChatData chatData = new ChatData(param[0],param[1]);
return chatData;
}
@Override
protected void onPostExecute(ChatData chatData) {
mChatAdapter.add(chatData);
mChatLv.smoothScrollToPosition(mChatAdapter.getCount()-1);
super.onPostExecute(chatData);
}
}.execute(name,message);
}
}, String.class,String.class);
//開啟連線
try {
mSignalRFuture.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
//關閉連線
mSignalRFuture.cancel();
super.onDestroy();
}
}
ChatData資料容器
public class ChatData {
private String name;
private String message;
public ChatData(String name, String message) {
this.name = name;
this.message = message;
}
public String getName() {
return name;
}
public String getMessage() {
return message;
}
}
ChatAdapter,這邊比較需要講一下的只有
我將自己的聊天內容標註為紅色而已
public class ChatAdapter extends ArrayAdapter<ChatData>{
private String mName;
public ChatAdapter(Context context, int resource, List<ChatData> objects,String mName) {
super(context, resource, objects);
this.mName = mName;
}
private class ViewHolder {
TextView nameTv;
TextView messageTv;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ChatData chatData = getItem(position);
ViewHolder holder;
if(convertView==null){
holder = new ViewHolder();
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item, null);
holder.nameTv = (TextView) convertView.findViewById(R.id.nameTv);
holder.messageTv = (TextView) convertView.findViewById(R.id.messageTv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.nameTv.setText(chatData.getName());
holder.messageTv.setText(chatData.getMessage());
if(chatData.getName().equals(mName)){
holder.nameTv.setTextColor(Color.RED);
}
return convertView;
}
}
3.完成了!來看效果吧
android與brower對話





