实现了基本的socket通信(即两台设备,一台用作服务器,一台用作客户端),服务器进行监听,客户端发送加密数据到服务器,服务器进行解密得到明文。
注意:本项目中使用了ButterKnife及EventBus作为辅助工具,通信建立时默认网络正常(未做局域网网络环境检测),加密方式为AES加密
1.效果图:
(1)客户端

(2)服务器端

2.界面布局部分
(1)服务器端布局 function_socket_server.xml
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:orientation
=
"vertical"
>
<
RelativeLayout
style
=
"@style/ToolBar"
>
<
TextView
style
=
"@style/ToolBar_tv_Title"
android:text
=
"网络加密-服务器端"
/>
</
RelativeLayout
>
<
LinearLayout
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:orientation
=
"horizontal"
>
<
Button
android:id
=
"@+id/btn_startListener"
android:layout_width
=
"0dp"
android:layout_height
=
"wrap_content"
android:layout_weight
=
"1"
android:text
=
"启动监听"
/>
<
Button
android:id
=
"@+id/btn_stopListener"
android:layout_width
=
"0dp"
android:layout_height
=
"wrap_content"
android:layout_weight
=
"1"
android:text
=
"停止监听"
/>
<
Button
android:id
=
"@+id/btn_getUser"
android:layout_width
=
"0dp"
android:layout_height
=
"wrap_content"
android:layout_weight
=
"1"
android:text
=
"刷新用户"
/>
</
LinearLayout
>
<
LinearLayout
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:orientation
=
"horizontal"
android:padding
=
"10dp"
>
<
TextView
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:text
=
"本机地址:"
/>
<
TextView
android:id
=
"@+id/tv_localAddress"
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:singleLine
=
"true"
/>
</
LinearLayout
>
<
ScrollView
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
>
<
LinearLayout
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:orientation
=
"vertical"
>
<
TextView
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:text
=
"接收到的明文:"
android:textColor
=
"@color/black"
/>
<
TextView
android:id
=
"@+id/tv_receivedContent"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:padding
=
"10dp"
/>
<
TextView
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:text
=
"解密后的明文:"
android:textColor
=
"@color/black"
/>
<
TextView
android:id
=
"@+id/tv_decryptContent"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:padding
=
"10dp"
/>
</
LinearLayout
>
</
ScrollView
>
</
LinearLayout
>
(2)客户端布局 function_socket_client.xml
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:orientation
=
"vertical"
>
<
RelativeLayout
style
=
"@style/ToolBar"
>
<
TextView
style
=
"@style/ToolBar_tv_Title"
android:text
=
"网络加密-客户端"
/>
</
RelativeLayout
>
<
LinearLayout
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:orientation
=
"horizontal"
android:padding
=
"10dp"
>
<
TextView
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:text
=
"服务器地址:"
/>
<
EditText
android:id
=
"@+id/edtTxt_serverAddress"
android:layout_width
=
"match_parent"
android:text
=
"192.168.43.1"
android:layout_height
=
"wrap_content"
android:singleLine
=
"true"
/>
</
LinearLayout
>
<
ScrollView
android:layout_width
=
"match_parent"
android:layout_height
=
"0dp"
android:layout_weight
=
"1"
>
<
LinearLayout
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:orientation
=
"vertical"
>
<
TextView
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:text
=
"文本内容:"
android:textColor
=
"@color/black"
/>
<
EditText
android:id
=
"@+id/edtTxt_Content"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:background
=
"@color/main_background"
android:padding
=
"10dp"
android:text
=
"123木头人"
/>
</
LinearLayout
>
</
ScrollView
>
<
Button
android:id
=
"@+id/btn_encryptAndSend"
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"bottom"
android:text
=
"加密并发送"
/>
</
LinearLayout
>
(3)用到的style
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22<!--通用Title的右侧按钮-->
<style name=
"ToolBar_iv_Right"
>
<item name=
"android:layout_width"
>@dimen/toolbar_icon_dimen</item>
<item name=
"android:layout_height"
>@dimen/toolbar_icon_dimen</item>
<item name=
"android:layout_alignParentRight"
>true</item>
<item name=
"android:layout_gravity"
>end</item>
<item name=
"android:clickable"
>true</item>
<item name=
"android:background"
>?android:actionBarItemBackground</item>
<item name=
"android:padding"
>
15
dp</item>
</style>
<!--通用Title的TextView-->
<style name=
"ToolBar_tv_Title"
>
<item name=
"android:layout_width"
>wrap_content</item>
<item name=
"android:layout_height"
>wrap_content</item>
<item name=
"android:layout_centerVertical"
>true</item>
<item name=
"android:layout_marginLeft"
>@dimen/toolbar_title_haveBack_marginStart</item>
<item name=
"android:layout_marginRight"
>@dimen/toolbar_title_haveBack_marginEnd</item>
<item name=
"android:gravity"
>
center
</item>
<item name=
"android:singleLine"
>true</item>
<item name=
"android:textColor"
>@color/
white
</item>
<item name=
"android:textSize"
>
20
sp</item>
</style>
3.功能代码
(1)基类 baseEventActivity.Java
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31import
android.os.Bundle;
import
android.support.v7.app.AppCompatActivity;
import
org.greenrobot.eventbus.EventBus;
import
butterknife.ButterKnife;
public
abstract
class
baseEventActivity
extends
AppCompatActivity {
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
getIntentData();
setContentView(getLayoutResId());
ButterKnife.bind(
this
);
EventBus.getDefault().register(
this
);
init();
}
protected
void
getIntentData() {
}
@Override
protected
void
onDestroy() {
super
.onDestroy();
EventBus.getDefault().unregister(
this
);
}
protected
abstract
void
init();
protected
abstract
int
getLayoutResId();
}
(2)服务器主界面 Function_Socket.java
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126import
android.content.ComponentName;
import
android.content.Intent;
import
android.content.ServiceConnection;
import
android.os.IBinder;
import
android.view.View;
import
android.widget.TextView;
import
org.greenrobot.eventbus.Subscribe;
import
org.greenrobot.eventbus.ThreadMode;
import
java.io.BufferedReader;
import
java.io.FileReader;
import
java.util.ArrayList;
import
butterknife.BindView;
import
butterknife.OnClick;
public
class
Function_Socket_Server
extends
baseEventActivity {
@BindView
(R.id.tv_localAddress)
TextView tv_localAddress;
@BindView
(R.id.tv_receivedContent)
TextView tv_receivedContent;
@BindView
(R.id.tv_decryptContent)
TextView tv_decryptContent;
private
LocalService localService;
//用于启动监听的服务
private
ServiceConnection sc;
//服务连接
@Override
protected
void
init() {
tv_localAddress.setText(ToolUtil.getHostIP());
sc =
new
ServiceConnection() {
@Override
public
void
onServiceConnected(ComponentName name, IBinder service) {
LocalService.LocalBinder localBinder = (LocalService.LocalBinder) service;
localService = localBinder.getService();
localService.startWaitDataThread();
ToastUtil.showToast(Function_Socket_Server.
this
,
"监听已启动"
);
}
@Override
public
void
onServiceDisconnected(ComponentName name) {
}
};
connection();
}
@Subscribe
(threadMode = ThreadMode.MAIN)
public
void
getData(String data) {
tv_receivedContent.setText(data);
tv_decryptContent.setText(AESUtil.decrypt(ConstantUtil.password, data));
}
private
void
connection() {
Intent intent =
new
Intent(
this
, LocalService.
class
);
bindService(intent, sc, BIND_AUTO_CREATE);
}
@Override
protected
int
getLayoutResId() {
return
R.layout.function_socket_server;
}
private
ArrayList<String> getConnectedIP() {
ArrayList<String> connectedIP =
new
ArrayList<>();
try
{
//通过读取配置文件实现
BufferedReader br =
new
BufferedReader(
new
FileReader(
"/proc/net/arp"
));
String line;
while
((line = br.readLine()) !=
null
) {
String[] splitted = line.split(
" +"
);
if
(splitted.length >=
4
) {
String ip = splitted[
0
];
connectedIP.add(ip);
}
}
}
catch
(Exception e) {
e.printStackTrace();
}
return
connectedIP;
}
@OnClick
({R.id.btn_startListener, R.id.btn_stopListener, R.id.btn_getUser})
public
void
onClick(View v) {
switch
(v.getId()) {
case
R.id.btn_startListener:
//启动监听
connection();
break
;
case
R.id.btn_stopListener:
//停止监听
if
(sc !=
null
)
unbindService(sc);
break
;
case
R.id.btn_getUser:
//刷新连接到此设备的IP并清空之前接收到的数据
ArrayList<String> connectedIP = getConnectedIP();
StringBuilder resultList =
new
StringBuilder();
for
(String ip : connectedIP) {
resultList.append(ip);
resultList.append(
"n"
);
}
ToastUtil.showToast(
this
,
"连接到手机上的Ip是:"
+ resultList.toString());
tv_decryptContent.setText(
""
);
tv_receivedContent.setText(
""
);
break
;
}
}
public
void
onDestroy() {
super
.onDestroy();
if
(sc !=
null
)
unbindService(sc);
}
}
(3)客户端主界面 Function_Socket_Client.java
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125import
android.app.ProgressDialog;
import
android.util.Log;
import
android.view.View;
import
android.widget.EditText;
import
org.greenrobot.eventbus.Subscribe;
import
org.greenrobot.eventbus.ThreadMode;
import
butterknife.BindView;
import
butterknife.OnClick;
public
class
Function_Socket_Client
extends
baseEventActivity {
@BindView
(R.id.edtTxt_Content)
EditText edtTxt_Content;
@BindView
(R.id.edtTxt_serverAddress)
EditText edtTxt_serverAddress;
private
ProgressDialog mProgressDialog;
//加载的小菊花
@Override
protected
void
init() {
}
@Override
protected
int
getLayoutResId() {
return
R.layout.function_socket_client;
}
@OnClick
(R.id.btn_encryptAndSend)
public
void
onClick(View v) {
switch
(v.getId()) {
case
R.id.btn_encryptAndSend:
String s = edtTxt_Content.getText().toString().trim();
String ip = edtTxt_serverAddress.getText().toString().trim();
if
(ToolUtil.IsIpv4(ip)) {
new
SendDataThread(ip, AESUtil.encrypt(ConstantUtil.password, s), ConstantUtil.port).start();
//消息发送方启动线程发送消息
showProgressDialog(
"尝试发送数据到ntt"
+ ip,
true
);
}
else
{
ToastUtil.showToast(
this
,
"IP不合法!"
);
}
break
;
}
}
@Subscribe
(threadMode = ThreadMode.MAIN)
public
void
sendResult(Integer resultCode) {
Log.i(
"succ"
,
"="
+ resultCode);
dismissProgressDialog();
switch
(resultCode) {
case
ConstantUtil.CODE_SUCCESS:
ToastUtil.showToast(
this
,
"发送成功"
);
break
;
case
ConstantUtil.CODE_TIMEOUT:
ToastUtil.showToast(
this
,
"连接超时"
);
break
;
case
ConstantUtil.CODE_UNKNOWN_HOST:
ToastUtil.showToast(
this
,
"错误-未知的host"
);
break
;
}
}
public
void
showProgressDialog(
final
String msg,
final
boolean
isCancel) {
runonUiThread(
new
Runnable() {
@Override
public
void
run() {
try
{
if
(mProgressDialog ==
null
) {
mProgressDialog =
new
ProgressDialog(Function_Socket_Client.
this
);
}
if
(mProgressDialog.isShowing()) {
return
;
}
mProgressDialog.setMessage(msg);
mProgressDialog.setCancelable(isCancel);
mProgressDialog.setCanceledonTouchOutside(
false
);
mProgressDialog.setonCancelListener(
null
);
mProgressDialog.show();
}
catch
(Exception e) {
e.printStackTrace();
}
}
});
}
public
void
dismissProgressDialog() {
try
{
if
(mProgressDialog !=
null
&& mProgressDialog.isShowing()) {
runonUiThread(
new
Runnable() {
@Override
public
void
run() {
mProgressDialog.dismiss();
}
}
);
}
}
catch
(Exception e) {
e.printStackTrace();
}
}
}
(4)LocalService.java
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34import
android.app.Service;
import
android.content.Intent;
import
android.os.Binder;
import
android.os.IBinder;
public
class
LocalService
extends
Service {
private
IBinder iBinder =
new
LocalService.LocalBinder();
@Override
public
IBinder onBind(Intent intent) {
return
iBinder;
}
@Override
public
int
onStartCommand(Intent intent,
int
flags,
int
startId) {
return
START_STICKY;
}
public
void
startWaitDataThread() {
new
ListenThread(ConstantUtil.port).start();
}
//定义内容类继承Binder
public
class
LocalBinder
extends
Binder {
//返回本地服务
public
LocalService getService() {
return
LocalService.
this
;
}
}
}
(5)ListenThread.java
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45import
org.greenrobot.eventbus.EventBus;
import
java.io.BufferedReader;
import
java.io.IOException;
import
java.io.InputStream;
import
java.io.InputStreamReader;
import
java.net.ServerSocket;
import
java.net.Socket;
public
class
ListenThread
extends
Thread {
private
ServerSocket serverSocket;
public
ListenThread(
int
port) {
try
{
serverSocket =
new
ServerSocket(port);
}
catch
(IOException e) {
e.printStackTrace();
}
}
@Override
public
void
run() {
while
(
true
) {
try
{
if
(serverSocket !=
null
) {
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
if
(inputStream !=
null
) {
BufferedReader in =
new
BufferedReader(
new
InputStreamReader(inputStream,
"UTF-8"
));
String str;
str = in.readLine();
EventBus.getDefault().post(str);
socket.close();
}
}
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
}
(6)SendDataThread.java
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57import
android.util.Log;
import
org.greenrobot.eventbus.EventBus;
import
java.io.BufferedWriter;
import
java.io.IOException;
import
java.io.OutputStream;
import
java.io.OutputStreamWriter;
import
java.net.InetSocketAddress;
import
java.net.Socket;
import
java.net.SocketTimeoutException;
import
java.net.UnknownHostException;
public
class
SendDataThread
extends
Thread {
private
Socket socket;
private
String ip;
//接收方的IP
private
int
port;
//接收方的端口号
private
String data;
//准备发送的数据
public
SendDataThread(String ip, String data,
int
port) {
this
.ip = ip;
this
.data = data;
this
.port = port;
}
@Override
public
void
run() {
try
{
socket =
new
Socket();
socket.connect(
new
InetSocketAddress(ip,port),ConstantUtil.TIME_MILLIS);
//设置超时时间
}
catch
(UnknownHostException e) {
EventBus.getDefault().post(ConstantUtil.CODE_UNKNOWN_HOST);
Log.d(
"error"
,
"SendDataThread.init() has UnknownHostException"
+ e.getMessage());
}
catch
(SocketTimeoutException e) {
EventBus.getDefault().post(ConstantUtil.CODE_TIMEOUT);
Log.d(
"error"
,
"SendDataThread.init() has TimeoutException:"
+ e.getMessage());
}
catch
(IOException e){
Log.d(
"error"
,
"SendDataThread.init() has IOException:"
+ e.getMessage());
}
if
(socket !=
null
&&socket.isConnected()) {
try
{
OutputStream ops = socket.getOutputStream();
OutputStreamWriter opsw =
new
OutputStreamWriter(ops);
BufferedWriter writer =
new
BufferedWriter(opsw);
writer.write(data +
"rnrn"
);
//由于socket使用缓冲区进行读写数据,因此使用rnrn用于表明数据已写完.不加这个会导致数据无法发送
EventBus.getDefault().post(ConstantUtil.CODE_SUCCESS);
writer.flush();
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
}
(7)AESUtil.java
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142import
android.util.Log;
import
java.io.UnsupportedEncodingException;
import
javax.crypto.Cipher;
import
javax.crypto.spec.IvParameterSpec;
import
javax.crypto.spec.SecretKeySpec;
public
class
AESUtil {
// private static final String CipherMode = "AES/ECB/PKCS5Padding";使用ECB加密,不需要设置IV,但是不安全
private
static
final
String CipherMode =
"AES/CFB/NoPadding"
;
//使用CFB加密,需要设置IV
private
static
SecretKeySpec createKey(String password) {
byte
[] data =
null
;
if
(password ==
null
) {
password =
""
;
}
StringBuilder sb =
new
StringBuilder(
32
);
sb.append(password);
while
(sb.length() <
32
) {
sb.append(
"0"
);
}
if
(sb.length() >
32
) {
sb.setLength(
32
);
}
try
{
data = sb.toString().getBytes(
"UTF-8"
);
}
catch
(UnsupportedEncodingException e) {
e.printStackTrace();
}
return
new
SecretKeySpec(data,
"AES"
);
}
//
private
static
byte
[] encrypt(
byte
[] content, String password) {
try
{
SecretKeySpec key = createKey(password);
System.out.println(key);
Cipher cipher = Cipher.getInstance(CipherMode);
cipher.init(Cipher.ENCRYPT_MODE, key,
new
IvParameterSpec(
new
byte
[cipher.getBlockSize()]));
return
cipher.doFinal(content);
}
catch
(Exception e) {
e.printStackTrace();
}
return
null
;
}
//
public
static
String encrypt(String password, String content) {
Log.d(
"加密前"
,
"seed="
+ password +
"ncontent="
+ content);
byte
[] data =
null
;
try
{
data = content.getBytes(
"UTF-8"
);
}
catch
(Exception e) {
e.printStackTrace();
}
data = encrypt(data, password);
String result = byte2hex(data);
Log.d(
"加密后"
,
"result="
+ result);
return
result;
}
//
private
static
byte
[] decrypt(
byte
[] content, String password) {
try
{
SecretKeySpec key = createKey(password);
Cipher cipher = Cipher.getInstance(CipherMode);
cipher.init(Cipher.DECRYPT_MODE, key,
new
IvParameterSpec(
new
byte
[cipher.getBlockSize()]));
return
cipher.doFinal(content);
}
catch
(Exception e) {
e.printStackTrace();
}
return
null
;
}
//
public
static
String decrypt(String password, String content) {
Log.d(
"解密前"
,
"seed="
+ password +
"ncontent="
+ content);
byte
[] data =
null
;
try
{
data = hex2byte(content);
}
catch
(Exception e) {
e.printStackTrace();
}
data = decrypt(data, password);
if
(data ==
null
)
return
null
;
String result =
null
;
try
{
result =
new
String(data,
"UTF-8"
);
Log.d(
"解密后"
,
"result="
+ result);
}
catch
(UnsupportedEncodingException e) {
e.printStackTrace();
}
return
result;
}
//
private
static
String byte2hex(
byte
[] b) {
// 一个字节的数,
StringBuilder sb =
new
StringBuilder(b.length *
2
);
String tmp ;
for
(
byte
aB : b) {
// 整数转成十六进制表示
tmp = (Integer.toHexString(aB &
0xFF
));
if
(tmp.length() ==
1
) {
sb.append(
"0"
);
}
sb.append(tmp);
}
return
sb.toString().toUpperCase();
// 转成大写
}
//
private
static
byte
[] hex2byte(String inputString) {
if
(inputString ==
null
|| inputString.length() <
2
) {
return
new
byte
[
0
];
}
inputString = inputString.toLowerCase();
int
l = inputString.length() /
2
;
byte
[] result =
new
byte
[l];
for
(
int
i =
0
; i < l; ++i) {
String tmp = inputString.substring(
2
* i,
2
* i +
2
);
result[i] = (
byte
) (Integer.parseInt(tmp,
16
) &
0xFF
);
}
return
result;
}
}
(8)ConstantUti.java
?
1 2 3 4 5 6 7 8 9 10 11
public
class
ConstantUtil {
public
static
final
int
TIME_MILLIS =
5
*
1000
;
//连接超时时间
public
static
final
int
port =
25256
;
//端口号
public
static
final
String password =
"123456885"
;
//加密所使用的密钥
public
static
final
int
CODE_TIMEOUT =
0
;
//连接超时
public
static
final
int
CODE_SUCCESS =
1
;
//连接成功
public
static
final
int
CODE_UNKNOWN_HOST =
2
;
//错误-未知的host
}
(9)ToolUtil.java
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71import
android.util.Log;
import
java.net.Inet6Address;
import
java.net.InetAddress;
import
java.net.NetworkInterface;
import
java.net.SocketException;
import
java.util.Enumeration;
public
class
ToolUtil {
public
static
String getHostIP() {
String hostIp =
null
;
try
{
Enumeration nis = NetworkInterface.getNetworkInterfaces();
InetAddress ia;
while
(nis.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) nis.nextElement();
Enumeration<InetAddress> ias = ni.getInetAddresses();
while
(ias.hasMoreElements()) {
ia = ias.nextElement();
if
(ia
instanceof
Inet6Address) {
continue
;
// skip ipv6
}
String ip = ia.getHostAddress();
if
(!
"127.0.0.1"
.equals(ip)) {
hostIp = ia.getHostAddress();
break
;
}
}
}
}
catch
(SocketException e) {
Log.i(
"error"
,
"SocketException"
);
e.printStackTrace();
}
return
hostIp;
}
public
static
boolean
IsIpv4(String ipv4) {
if
(ipv4 ==
null
|| ipv4.length() ==
0
) {
return
false
;
//字符串为空或者空串
}
String[] parts = ipv4.split(
"."
);
//因为java doc里已经说明, split的参数是reg, 即正则表达式, 如果用"|"分割, 则需使用"|"
if
(parts.length !=
4
) {
return
false
;
//分割开的数组根本就不是4个数字
}
for
(String part : parts) {
try
{
int
n = Integer.parseInt(part);
if
(n <
0
|| n >
255
) {
return
false
;
//数字不在正确范围内
}
}
catch
(NumberFormatException e) {
return
false
;
//转换数字不正确
}
}
return
true
;
}
}
(10)ToastUtil.java
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27import
android.content.Context;
import
android.widget.Toast;
public
class
ToastUtil {
private
static
Toast mToast =
null
;
public
static
void
showToast(Context context, String text) {
if
(text !=
null
) {
if
(mToast ==
null
) {
mToast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
}
else
{
mToast.setText(text);
mToast.setDuration(Toast.LENGTH_SHORT);
}
mToast.show();
}
}
}
3.权限及声明
?
1 2 3 4 5<
uses-permission
android:name
=
"android.permission.INTERNET"
/>
<
uses-permission
android:name
=
"android.permission.ACCESS_WIFI_STATE"
/>
<
uses-permission
android:name
=
"android.permission.CHANGE_WIFI_STATE"
/>
<!--service部分-->
<
service
android:name
=
"com.test.test.LocalService"
/>