[size=x-small]
初学android,没有急于去了解android各种图形类的用法,毕竟每个学Android都有一颗做游戏的心。但是通讯这一块才是一个移动终端最需要去了解的有关socket,由于之前没有怎么接触,这次借着学android的机遇学习了一下,下面就讲我我自己一个简单的socket例子。
之前是想写一个建议聊天室的,网上有很多人都实现了,但是文章都是抄来抄去,代码也都稀稀散散不完全,给很多初学的人很莫名的感觉,在做点对点聊天之前,先明白socket怎么样通讯才是至关重要的。在做socket之前或许,用httpclient访问下PC服务器这些例子也可以尝试下,起码能熟悉android通讯中流的一些用法。
我做了一个简单的app,毕竟是给手机之间用,它肯定有一个server端,一个client端。先把界面展示一下。
[img]http://dl2.iteye.com/upload/attachment/0092/6005/ab4079d2-1c70-3109-bec6-77d10e1cd040.png[/img]
如果是server端,载入界面后就点击server端按钮,服务器就阻塞直到客户端请求,然后进入本地联系人查询页面,选好本地联系人,将联系人发送给请求端。
服务器端代码:
client端载入页面选择好请求方的IP地址点击建立连接,完成一次请求。
客户端代码:
MainActivity.java
Object流对象:
界面布局:
activity_main.xml:
联系人选择布局:
conperson.xml
AndroidManifest.xml
备注:有些权限没有用到,可适当更改,有预留给其他功能开发用。[/size]
初学android,没有急于去了解android各种图形类的用法,毕竟每个学Android都有一颗做游戏的心。但是通讯这一块才是一个移动终端最需要去了解的有关socket,由于之前没有怎么接触,这次借着学android的机遇学习了一下,下面就讲我我自己一个简单的socket例子。
之前是想写一个建议聊天室的,网上有很多人都实现了,但是文章都是抄来抄去,代码也都稀稀散散不完全,给很多初学的人很莫名的感觉,在做点对点聊天之前,先明白socket怎么样通讯才是至关重要的。在做socket之前或许,用httpclient访问下PC服务器这些例子也可以尝试下,起码能熟悉android通讯中流的一些用法。
我做了一个简单的app,毕竟是给手机之间用,它肯定有一个server端,一个client端。先把界面展示一下。
[img]http://dl2.iteye.com/upload/attachment/0092/6005/ab4079d2-1c70-3109-bec6-77d10e1cd040.png[/img]
如果是server端,载入界面后就点击server端按钮,服务器就阻塞直到客户端请求,然后进入本地联系人查询页面,选好本地联系人,将联系人发送给请求端。
服务器端代码:
package com.exmessage;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.app.AlertDialog;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class PServer implements Runnable {
private TextView meesage;//聊天记录
private int zsflag=0;//阻塞flag
private ServerSocket server;
private Activity context;
private Handler handler;
int count = 1;
private ListView listview;
private Allmessageobj messageobj =new Allmessageobj();//传输信息对象载体
private Map objmap=new HashMap();
private Allmessageobj returnobj=new Allmessageobj();
private OnItemClickListener myonclister;
private Socket client=new Socket();
private OutputStream outdata ;
public PServer(Activity contextarg) {
try {
context=contextarg;
meesage=(TextView)context.findViewById(R.id.textView1);//连接信息框
//创建属于主线程的handler
handler=new Handler();
server=new ServerSocket(10010);
new Thread(this).start();
context.setContentView(R.layout.conperson);
listview=(ListView)context.findViewById(R.id.listView1);
myonclister=new OnItemClickListener(){//添加事件
public void onItemClick(AdapterView<?> arg0, View arg1,int arg2, long arg3) {
// OutputStream outdata = client.getOutputStream();
try {
Object objs=objmap.get(arg2);
returnobj=(Allmessageobj)objs;
zsflag=1;
context.setContentView(R.layout.activity_main);
TextView tsmessag=(TextView)context.findViewById(R.id.textView1);
EditText etx=(EditText)context.findViewById(R.id.search);
etx.setCursorVisible(false);
etx.setFocusable(false);
etx.setFocusableInTouchMode(false);
tsmessag.setText("发送<"+returnobj.getName()+":"+returnobj.getPhonenum()+">成功!目标IP<"+String.valueOf(client.getInetAddress())+">");
java.io.ByteArrayOutputStream bop = new java.io.ByteArrayOutputStream();
java.io.ObjectOutputStream oop;
oop = new java.io.ObjectOutputStream(bop);
oop.writeObject(returnobj);
outdata.write(bop.toByteArray());
outdata.flush();
outdata.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}};
listview.setOnItemClickListener(myonclister);
} catch (IOException e) {
// TODO Auto-generated catch block
new AlertDialog.Builder(context).setTitle("提示").setMessage(String.valueOf(e)).setPositiveButton("OK", null).show();
}
}
public void run() {
try {
// handler.post(runnableUi);
while(true){
client=server.accept();
handler.post(listviewUi);
outdata = client.getOutputStream();
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("服务器 run 异常: " + e.getMessage());
}
}
/* 读取命令 */
public static String readCMDFromSocket(InputStream in)
{
int MAX_BUFFER_BYTES = 2048;
String msg = "";
byte[] tempbuffer = new byte[MAX_BUFFER_BYTES];
try
{
int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length);
msg = new String(tempbuffer, 0, numReadedBytes, "utf-8");
tempbuffer = null;
} catch (Exception e)
{
e.printStackTrace();
}
return msg;
}
Runnable runnableUi=new Runnable(){
public void run() {
//更新界面
meesage.setText("信息:"+messageobj.getMessage()+"....");
//meesage.setText(meesage.getText()+"\n"+messageobj.getIpaddress()+":"+messageobj.getMessage());
}
};
Runnable listviewUi=new Runnable(){
public void run() {
context.setContentView(R.layout.conperson);
listview=(ListView)context.findViewById(R.id.listView1);
listview.setOnItemClickListener(myonclister);
//更新界面
List list=new ArrayList();
Uri uri = Uri.parse("content://com.android.contacts/contacts");
//String selection = "mimetype='vnd.android.cursor.item/contact_event' and data2='3'";
Cursor cursor = context.getContentResolver().query(uri, new String[]{"_id"}, null, null, null);
//Cursor cur = MainActivity.this.getContentResolver().query(ContactsContract.Data.CONTENT_URI, projection, selection, null, null);
List params=new ArrayList();
List datalist=new ArrayList();
while (cursor.moveToNext()) {
messageobj=new Allmessageobj();
int contractID = cursor.getInt(0);
StringBuilder sb = new StringBuilder();
// sb.append(contractID);
// Uri uri11 = ContactsContract.Contacts.CONTENT_URI;
uri = Uri.parse("content://com.android.contacts/contacts/" + contractID + "/data");
Cursor cursor1 = context.getContentResolver().query(uri, new String[]{"mimetype", "data1", "data2"}, null, null, null);
//UserPhoneVO vo=new UserPhoneVO();
while (cursor1.moveToNext()) {
String data1 = cursor1.getString(cursor1.getColumnIndex("data1"));
String mimeType = cursor1.getString(cursor1.getColumnIndex("mimetype"));
if ("vnd.android.cursor.item/name".equals(mimeType)) {
messageobj.setName(data1);
sb.append(data1+"-");
} else if ("vnd.android.cursor.item/email_v2".equals(mimeType)) {
sb.append( data1+"-");
} else if ("vnd.android.cursor.item/phone_v2".equals(mimeType)) {
sb.append(data1+"-");
messageobj.setPhonenum(data1);
}
}
datalist.add(messageobj);
cursor1.close();
}
cursor.close();
for(int i=0;i<datalist.size();i++){
Allmessageobj messavo=(Allmessageobj)datalist.get(i);
objmap.put(i,messavo);
params.add(messavo.getName()+":"+messavo.getPhonenum());
}
listview.setAdapter(new ArrayAdapter (context,android.R.layout.simple_list_item_1,params));
//listview.setAdapter(adapter);
// meesage.setText("信息:"+messageobj.getMessage()+"....");
//meesage.setText(meesage.getText()+"\n"+messageobj.getIpaddress()+":"+messageobj.getMessage());
}
};
}
client端载入页面选择好请求方的IP地址点击建立连接,完成一次请求。
客户端代码:
package com.exmessage;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Handler;
import android.widget.EditText;
import android.widget.TextView;
public class Client implements Runnable{
/** 端口号 */
public static final int PORT = 10010;
private Activity context;
private EditText txtvs;
private TextView dismes;//显示连接信息
/** ip 地址 */
public String IP;
private Allmessageobj returnobj=new Allmessageobj();
private Handler handler=new Handler();
public Client(Activity contextarg) {
context=contextarg;
txtvs=(EditText)context.findViewById(R.id.search);
dismes=(TextView)context.findViewById(R.id.textView1);
IP=String.valueOf(txtvs.getText());
//handler=new Handler();
//new AlertDialog.Builder(context).setTitle("提示").setMessage("连接:"+IP+"....").setPositiveButton("OK", null).show();
run();
}
public void run() {
Socket socket = null;
try {
// 创建一个流套接字并将其连接到指定主机上的指定端口号
//while (true) {
// 创建一个流套接字并将其连接到指定主机上的指定端口号
socket = new Socket(IP, PORT);
// 读取服务器端数据
//System.out.println("是否连接"+socket.isConnected());
// System.out.println("BufferSize"+socket.getReceiveBufferSize());
// String inputstr = new BufferedReader(new InputStreamReader(System.in)).readLine();
// InputStream inputStream = new ByteArrayInputStream(abc.toString().getBytes());
//String str = new BufferedReader(new InputStreamReader(inputStream)).readLine();
//ObjectOutputStream output=new ObjectOutputStream(socket.getOutputStream());
InputStream indata=socket.getInputStream();
//DataOutputStream outdata=new DataOutputStream(socket.getOutputStream());
//Allmessageobj outmessage=new Allmessageobj();
//outmessage.setMessage("已响应");
//outdata.writeObject(outmessage);
//outdata.writeUTF("请求中。。。");
//indata.read();
//byte b[] = utfstring.getBytes();
//String usus=indata.read();
//byte[] bytess=usus.getBytes();
java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
byte[] bt = new byte[2014];
//while(indata.read(bt)!= -1)
// {
indata.read(bt);
bout.write(bt,0,bt.length);
//}
java.io.ByteArrayInputStream biin = new ByteArrayInputStream(bout.toByteArray());
java.io.ObjectInputStream isr=new java.io.ObjectInputStream(biin);
Object obj = isr.readObject();
returnobj=(Allmessageobj)obj;
//dismes.setText(returnobj.getName()+"--"+returnobj.getPhonenum());
dismes.setText(returnobj.getName()+"--"+returnobj.getPhonenum());
new AlertDialog.Builder(context).setTitle("提示").setMessage(returnobj.getName()+"--"+returnobj.getPhonenum()).setPositiveButton("OK", null).show();
// handler.post(runnableUi);
//}
} catch (Exception e) {
new AlertDialog.Builder(context).setTitle("提示").setMessage(String.valueOf(e)).setPositiveButton("OK", null).show();
} finally {
if (socket != null) {
try {
socket.close();
} catch (Exception e) {
socket = null;
System.out.println("客户端 finally 异常: " + e.getMessage());
}
}
}
}
Runnable runnableUi=new Runnable(){
public void run() {
//更新界面
new AlertDialog.Builder(context).setTitle("提示").setMessage(returnobj.getName()+"--"+returnobj.getPhonenum()).setPositiveButton("OK", null).show();
//meesage.setText(meesage.getText()+"\n"+messageobj.getIpaddress()+":"+messageobj.getMessage());
}
};
}
MainActivity.java
package com.exmessage;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
private EditText etx;//IP地址
private TextView txtvs;//显示连接信息
private Button btsend;//建立连接
private String IPAddress;
private Button btserver;//server按钮
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btsend=(Button)findViewById(R.id.button1);
etx=(EditText)findViewById(R.id.search);
txtvs=(TextView)findViewById(R.id.textView1);
IPAddress=getlocalip();
txtvs.setText("本地WIFI-IP地址:"+IPAddress);//初始显示本地IP
btserver=(Button)findViewById(R.id.button2);
/**
* SERVER端事件
*/
btserver.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
/**
* IP输入只读
*/
etx.setCursorVisible(false);
etx.setFocusable(false);
etx.setFocusableInTouchMode(false);
//开启server端线程
new AlertDialog.Builder(MainActivity.this).setTitle("提示").setMessage("启动server端监听").setPositiveButton("OK", null).show();
new PServer(MainActivity.this);
}
});
/**
* client端事件
*/
btsend.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
/**
* IP输入只读
*/
etx.setCursorVisible(false);
etx.setFocusable(false);
etx.setFocusableInTouchMode(false);
//开启server端线程
//new AlertDialog.Builder(MainActivity.this).setTitle("提示").setMessage("启动请求......").setPositiveButton("OK", null).show();
new Client(MainActivity.this);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
/**
* 通过wifi连接获取IP地址
* @return
*/
private String getlocalip(){
WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int ipAddress = wifiInfo.getIpAddress();
// Log.d(Tag, "int ip "+ipAddress);
if(ipAddress==0)return null;
return ((ipAddress & 0xff)+"."+(ipAddress>>8 & 0xff)+"."
+(ipAddress>>16 & 0xff)+"."+(ipAddress>>24 & 0xff));
}
}
Object流对象:
package com.exmessage;
import java.io.Serializable;
public class Allmessageobj implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1579114883234266292L;
public String ipaddress;
public String message;
public String flagcode;
public String name;
public String phonenum;
public String getIpaddress() {
return ipaddress;
}
public void setIpaddress(String ipaddress) {
this.ipaddress = ipaddress;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getFlagcode() {
return flagcode;
}
public void setFlagcode(String flagcode) {
this.flagcode = flagcode;
}
public String toString(){
return name+"----"+phonenum;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhonenum() {
return phonenum;
}
public void setPhonenum(String phonenum) {
this.phonenum = phonenum;
}
}
界面布局:
activity_main.xml:
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TableRow
android:id="@+id/tableRow1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<EditText
android:id="@+id/search"
android:layout_width="140dip"
android:layout_height="wrap_content"
android:hint="@string/search_hint"
android:imeOptions="actionSend"
android:inputType="text"
android:singleLine="true" >
<requestFocus />
</EditText>
<Button
android:id="@+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/connbegain" />
<Button
android:id="@+id/button2"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/asserver" />
</TableRow>
<TableRow
android:id="@+id/tableRow2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.01" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</TableRow>
</LinearLayout>
联系人选择布局:
conperson.xml
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exmessage"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!-- <uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />
-->
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.exmessage.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
备注:有些权限没有用到,可适当更改,有预留给其他功能开发用。[/size]