通過一段時間的學習和應用,了解了Android通信,通過這篇文章記錄一下學習過程。
基于ESP8266的Android WiFi通信廣泛應用于物聯網領域,常用是通過區域網路實作Android端和下位機的通信,達到控制目的。
此篇文章記錄的内容,需要手機連接配接到WiFi子產品,通過wifi讓Android端和硬體部分處于同一個區域網路内。Android網絡通信通過socket程式設計實作網絡的連接配接,通過IO流實作資料的發送與接收。
首先,建立一個Android項目,首先,需要給予APP網絡權限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
第二步,建立一個類SendThead,内容為發送和接收的代碼,首先定義IP,端口port,以及接收/發送’變量,打開套接字實作網絡的連接配接,連接配接結束關閉套接字,采取多線程實作資訊的發送與接收:
package com.example.a14942.smart_see;
/**
* Created by 14942 on 2018/3/26.
*/
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
class SendThread implements Runnable {
private String ip;
private int port;
BufferedReader in;
PrintWriter out; //列印流
Handler mainHandler;
Socket s;
private String receiveMsg;
ArrayList<String> list = new ArrayList<String>();
public SendThread(String ip,int port, Handler mainHandler) { //IP,端口,資料
this.ip = ip;
this.port=port;
this.mainHandler = mainHandler;
}
/**
* 套接字的打開
*/
void open(){
try {
s = new Socket(ip, port);
//in收單片機發的資料
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
s.getOutputStream())), true);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 套接字的關閉
*/
void close(){
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
//建立套接字
open();
//BufferedReader
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(200);
close();
open();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
if (!s.isClosed()) {
if (s.isConnected()) {
if (!s.isInputShutdown()) {
try {
Log.i("mr", "等待接收資訊");
char[] chars = new char[1024]; //byte[] bys = new byte[1024];
int len = 0; //int len = 0;
while((len = in.read(chars)) != -1){ //while((len = in.read(bys)) != -1) {
System.out.println("收到的消息: "+new String(chars, 0, len)); in.write(bys,0,len);
receiveMsg = new String(chars, 0, len); // }
Message msg=mainHandler.obtainMessage();
msg.what=0x00;
msg.obj=receiveMsg;
mainHandler.sendMessage(msg);
}
} catch (IOException e) {
Log.i("mr", e.getMessage());
try {
s.shutdownInput();
s.shutdownOutput();
s.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
}
}
}
});
thread.start();
while (true) {
//連接配接中
if (!s.isClosed()&&s.isConnected()&&!s.isInputShutdown()) {
// 如果消息集合有東西,并且發送線程在工作。
if (list.size() > 0 && !s.isOutputShutdown()) {
out.println(list.get(0));
list.remove(0);
}
Message msg=mainHandler.obtainMessage();
msg.what=0x01;
mainHandler.sendMessage(msg);
} else {
//連接配接中斷了
Log.i("mr", "連接配接斷開了");
Message msg=mainHandler.obtainMessage();
msg.what=0x02;
mainHandler.sendMessage(msg);
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
try {
out.close();
in.close();
s.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
public void send(String msg) {
System.out.println("msg的值為: " + msg);
list.add(msg);
}
}
第三步,建立主活動,編寫布局(xml)檔案,這裡我建立了一個溫度顯示框,和兩個開關控制按鈕(switch控件):
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/screen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/bb"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_x="30dp"
android:layout_y="130dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView2"
android:layout_width="50sp"
android:layout_height="wrap_content"
android:layout_marginLeft="33px"
android:text="濕度"
android:textColor="#000000"
android:textSize="18sp" />
<TextView
android:id="@+id/ttv2"
android:layout_width="160sp"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:text=""
android:textSize="18sp" />
<TextView
android:layout_width="60sp"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingLeft="10px"
android:text="%rh"
android:textColor="#000000"
android:textSize="18sp" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="開 關"
android:textColor="#000000"
android:textSize="18sp"
android:layout_x="50dp"
android:layout_y="200dp"
/>
<Switch
android:id="@+id/Switch2"
android:layout_width="50sp"
android:layout_height="wrap_content"
android:layout_weight="1.01"
android:layout_x="210dp"
android:layout_y="270dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="自動手動"
android:textColor="#000000"
android:textSize="18sp"
android:layout_x="50dp"
android:layout_y="270dp"
/>
<Switch
android:id="@+id/Switch1"
android:layout_width="50sp"
android:layout_height="wrap_content"
android:layout_x="210dp"
android:layout_y="200dp" />
</AbsoluteLayout>
第四步,編寫主活動,包括實作網絡連接配接(SendThead),實作消息的發送和接收,對開關控件(switch)定義點選事件:
package com.example.a14942.smart_see;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity{
/*接收發送定義的常量*/
private String mIp = "192.168.4.1";
private int mPort = 9000;
private SendThread sendthread;
String receive_Msg;
String l;
String total0,total1,total2,total3;
private Button button0;
private Button button1;
static PrintWriter mPrintWriterClient = null;
static BufferedReader mBufferedReaderClient = null;
Switch switch1,switch2;
/*****************************/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//getSupportActionBar().hide();
setContentView(R.layout.activity_main);
// button0= (Button)findViewById(R.id.Water_W_N);
// button0.setOnClickListener(button0ClickListener);
// button1= (Button)findViewById(R.id.Water_W_O);
// button1.setOnClickListener(button1ClickListener);
/***************連接配接*****************/
sendthread = new SendThread(mIp, mPort, mHandler);
Thread1();
new Thread().start();
/**********************************/
switch1 = (Switch) findViewById(R.id.Switch1);
switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked) {
sendthread.send("A");
} else {
sendthread.send("B");
}
}
});
switch2 = (Switch) findViewById(R.id.Switch2);
switch2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked) {
sendthread.send("C");
} else {
sendthread.send("D");
}
}
});
}
// private View.OnClickListener button0ClickListener = new View.OnClickListener() {
// public void onClick(View arg0) {
// mPrintWriterClient.print("j");
// mPrintWriterClient.flush();
//
// }
// };
// private View.OnClickListener button1ClickListener = new View.OnClickListener() {
// public void onClick(View arg0) {
// mPrintWriterClient.print("m");
// mPrintWriterClient.flush();
// }
// };
private class FragmentAdapter extends FragmentPagerAdapter {
List<Fragment> fragmentList = new ArrayList<Fragment>();
public FragmentAdapter(FragmentManager fm, List<Fragment> fragmentList) {
super(fm);
this.fragmentList = fragmentList;
}
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList.size();
}
}
/*接收線程*******************************************************************************/
/**
* 開啟socket連接配接線程
*/
void Thread1(){
// sendthread = new SendThread(mIp, mPort, mHandler);
new Thread(sendthread).start();//建立一個新線程
}
Handler mHandler = new Handler()
{
public void handleMessage(Message msg)
{
TextView text0 = (TextView)findViewById(R.id.ttv2);
super.handleMessage(msg);
if (msg.what == 0x00) {
Log.i("mr_收到的資料: ", msg.obj.toString());
receive_Msg = msg.obj.toString();
l = receive_Msg;
text0.setText(l);
}
}
};
}
這樣,一個簡單的物聯網通信就實作了。希望對大家有所幫助,如有疑問,歡迎留言。
本次文章一樣的源碼暫時找不到了,附上依托以上的代碼開發的簡單的demo示例
csdn:https://download.csdn.net/download/weixin_40042248/13456038
github:https://github.com/Yang-Jianlin/ESP8266-with-Android