Android一个简单的socket通信手机间推送联系人
16lz
2021-12-04
[size=x-small]
初学android,没有急于去了解android各种图形类的用法,毕竟每个学Android都有一颗做游戏的心。但是通讯这一块才是一个移动终端最需要去了解的有关socket,由于之前没有怎么接触,这次借着学android的机遇学习了一下,下面就讲我我自己一个简单的socket例子。
之前是想写一个建议聊天室的,网上有很多人都实现了,但是文章都是抄来抄去,代码也都稀稀散散不完全,给很多初学的人很莫名的感觉,在做点对点聊天之前,先明白socket怎么样通讯才是至关重要的。在做socket之前或许,用httpclient访问下PC服务器这些例子也可以尝试下,起码能熟悉android通讯中流的一些用法。
我做了一个简单的app,毕竟是给手机之间用,它肯定有一个server端,一个client端。先把界面展示一下。
如果是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端。先把界面展示一下。
如果是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;//阻塞flagprivate 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 blocke.printStackTrace();}}};listview.setOnItemClickListener(myonclister);} catch (IOException e) {// TODO Auto-generated catch blocknew 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按钮@Overrideprotected 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);//初始显示本地IPbtserver=(Button)findViewById(R.id.button2);/** * SERVER端事件 */btserver.setOnClickListener(new OnClickListener(){@Overridepublic 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(){@Overridepublic 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);}});}@Overridepublic 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]
更多相关文章
- Android自动连接指定的WiFi热点
- Android编程实现连接Wifi(运用Wifi 相关 API)
- AirPods怎么连接Android设备 AirPods与安卓设备连接方法
- Android(安卓)无线调试
- Android(安卓)客户端与服务器交互方式
- android客户端与服务器数据交换原则
- 【Android】蓝牙开发——BLE(低功耗蓝牙)(附完整Demo)
- 【Android开发】Android(安卓)Host详解(翻译自官方文档)
- 网络编程之——他山之石OkHttp