1.这是安卓APP实现的主活动------MainActivity.java
读这篇文章前,最好先阅读这篇索引文章
如果一点安卓基础都没有的,麻烦请先入门,另外学一学Android Studio的基础知识。
APP使用的是socket框架,通过tcp/ip协议与单片机通信。
由于我写这个代码的时候是大四第一学期刚开学临时学的,所以写的不是很好,代码也没有优化,包括UI也不美观,仅仅是实现了应有的功能而已。
对于没有加注释很抱歉,但是代码很短,基本上学过Java和安卓基础的都能看懂的,相信我。
如果你是一个安卓小白,并且已经安卓好Android Studio了,学会如何创建一个empty Activity了的话,那就创建好空的Activity之后,把对应的MainActivity.java和activity_main.xml代码替换成我给出来的代码就好啦!
package com.example.myclient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
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;
import android.widget.Toast;
public class MainActivity extends Activity {
private Button startButton,sendButtonClient,sendButtonClient1,sendButtonClient2,sendButtonClient3;
private EditText IPText,editMsgTextClient;
private Context mContext;
private boolean isConnecting=false;
private Thread mThreadClient=null;
private Socket mSocketClient=null;
static BufferedReader mBufferedReaderClient=null;
static PrintWriter mPrintWriterClient=null;
static int a=1;
private String recvMessageClient="";
private static TextView recvText,recvText1,recvText2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext=this;
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build()
);
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.penaltyLog()
.penaltyDeath()
.build());
IPText=(EditText) findViewById(R.id.IPText);
IPText.setText("172.16.2.184:8086");
startButton=(Button) findViewById(R.id.StartConnect);
startButton.setOnClickListener(StartClickListener);
//editMsgTextClient=(EditText) findViewById(R.id.clientMessageText);
//editMsgTextClient.setText("UP");
sendButtonClient=(Button) findViewById(R.id.SendButtonClient);
sendButtonClient.setOnClickListener(SendClickListenerClient);
sendButtonClient1=(Button) findViewById(R.id.SendButtonClient1);
sendButtonClient1.setOnClickListener(SendClickListenerClient1);
sendButtonClient2=(Button) findViewById(R.id.SendButtonClient2);
sendButtonClient2.setOnClickListener(SendClickListenerClient2);
sendButtonClient3=(Button) findViewById(R.id.SendButtonClient3);
sendButtonClient3.setOnClickListener(SendClickListenerClient3);
recvText=(TextView) findViewById(R.id.tv1);
recvText.setMovementMethod(ScrollingMovementMethod.getInstance());
recvText1=(TextView) findViewById(R.id.textView3);
recvText1.setMovementMethod(ScrollingMovementMethod.getInstance());
recvText2=(TextView) findViewById(R.id.textView4);
recvText2.setMovementMethod(ScrollingMovementMethod.getInstance());
}
private OnClickListener StartClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(isConnecting)
{
isConnecting = false;
try
{
if(mSocketClient!=null)
{
mSocketClient.close();
mSocketClient = null;
mPrintWriterClient.close();
mPrintWriterClient = null;
}
}catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
mThreadClient.interrupt();
startButton.setText("开始连接");
IPText.setEnabled(true);
recvText.setText("信息:\n");
}else
{
isConnecting=true;
startButton.setText("停止连接");
IPText.setEnabled(false);
mThreadClient = new Thread(mRunnable);
mThreadClient.start();
}
}
};
private OnClickListener SendClickListenerClient = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(isConnecting&&mSocketClient!=null)
{
//String msgText = editMsgTextClient.getText().toString();
String msgText ="c1\n";
if(msgText.length()<=0)
{
Toast.makeText(mContext, "发送内容不能为空!", Toast.LENGTH_SHORT).show();
}else
{
try
{
mPrintWriterClient.print(msgText);
mPrintWriterClient.flush();
}catch (Exception e) {
// TODO: handle exception
Toast.makeText(mContext, "发送异常:"+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}else
{
Toast.makeText(mContext, "没有连接", Toast.LENGTH_SHORT).show();
}
}
};
private OnClickListener SendClickListenerClient1 = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(isConnecting&&mSocketClient!=null)
{
//String msgText = editMsgTextClient.getText().toString();
String msgText ="c0\n";
if(msgText.length()<=0)
{
Toast.makeText(mContext, "发送内容不能为空!", Toast.LENGTH_SHORT).show();
}else
{
try
{
mPrintWriterClient.print(msgText);
mPrintWriterClient.flush();
}catch (Exception e) {
// TODO: handle exception
Toast.makeText(mContext, "发送异常:"+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}else
{
Toast.makeText(mContext, "没有连接", Toast.LENGTH_SHORT).show();
}
}
};
private OnClickListener SendClickListenerClient2 = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(isConnecting&&mSocketClient!=null)
{
//String msgText = editMsgTextClient.getText().toString();
String msgText ="t1\n";
if(msgText.length()<=0)
{
Toast.makeText(mContext, "发送内容不能为空!", Toast.LENGTH_SHORT).show();
}else
{
try
{
mPrintWriterClient.print(msgText);
mPrintWriterClient.flush();
}catch (Exception e) {
// TODO: handle exception
Toast.makeText(mContext, "发送异常:"+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}else
{
Toast.makeText(mContext, "没有连接", Toast.LENGTH_SHORT).show();
}
}
};
private OnClickListener SendClickListenerClient3 = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(isConnecting&&mSocketClient!=null)
{
//String msgText = editMsgTextClient.getText().toString();
String msgText ="t0\n";
if(msgText.length()<=0)
{
Toast.makeText(mContext, "发送内容不能为空!", Toast.LENGTH_SHORT).show();
}else
{
try
{
mPrintWriterClient.print(msgText);
mPrintWriterClient.flush();
}catch (Exception e) {
// TODO: handle exception
Toast.makeText(mContext, "发送异常:"+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}else
{
Toast.makeText(mContext, "没有连接", Toast.LENGTH_SHORT).show();
}
}
};
//线程:监听服务器发来的消息
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
String msgText = IPText.getText().toString();
if(msgText.length()<=0)
{
recvMessageClient="IP不能为空!\n";//消息换行
Message msg = new Message();
msg.what = 1;
mHandler.sendMessage(msg);
return;
}
int start = msgText.indexOf(":");
if((start==-1)||(start+1>=msgText.length()))
{
recvMessageClient = "IP地址不合法\n";
Message msg = new Message();
msg.what = 1;
mHandler.sendMessage(msg);
return;
}
String sIP= msgText.substring(0,start);
String sPort = msgText.substring(start+1);
int port = Integer.parseInt(sPort);
Log.d("gjz", "IP"+sIP+":"+port);
try
{
//连接服务器
mSocketClient = new Socket(sIP,port);
//取得输入、输出流
mBufferedReaderClient=new BufferedReader(new InputStreamReader(mSocketClient.getInputStream()));
mPrintWriterClient=new PrintWriter(mSocketClient.getOutputStream(),true);
recvMessageClient="已经连接到智能衣柜!\n";
Message msg = new Message();
msg.what = 1;
mHandler.sendMessage(msg);
}catch (Exception e) {
// TODO: handle exception
recvMessageClient = "连接IP异常:" + e.toString() + e.getMessage() + "\n";//消息换行
Message msg = new Message();
msg.what = 1;
mHandler.sendMessage(msg);
return;
}
char[] buffer = new char[256];
int count = 0;
while(isConnecting)
{
try
{
if((count = mBufferedReaderClient.read(buffer))>0)
{
recvMessageClient = getInfoBuff(buffer,count)+"\n";
Message msg = new Message();
msg.what = 1;
mHandler.sendMessage(msg);
}
}catch (Exception e) {
// TODO: handle exception
recvMessageClient = "接收异常:" + e.getMessage() + "\n";//消息换行
Message msg = new Message();
msg.what = 1;
mHandler.sendMessage(msg);
}
}
}
};
Handler mHandler = new Handler()
{
public void handleMessage(Message msg)
{
super.handleMessage(msg);
if(msg.what==1)
{
char []arrs=null;
while (a>0){
recvText.append(recvMessageClient);//刷新
a--;
}
arrs=recvMessageClient.toCharArray();
if (arrs[0]=='1'&&arrs[8]>=7){
//recvText.append("温湿度:"+arrs[5]+arrs[6]+"℃"+' '+arrs[8]+arrs[9]+"%\n");//刷新
//recvText1.append(arrs[5] + arrs[6] + "℃" + ' ' + arrs[8] + arrs[9] + "%\n");
recvText1.setText("温湿度: "+arrs[5] + arrs[6] + "℃" + ' ' + arrs[8] + arrs[9] + "% 差,请除湿\n");
}
else if (arrs[0]=='1'&&arrs[8]<7){
recvText1.setText("温湿度: "+arrs[5] + arrs[6] + "℃" + ' ' + arrs[8] + arrs[9] + "% 良\n");
}
else if (arrs[0]=='2'&&arrs[6]<'3'){
//recvText2.append(arrs[5]+arrs[6]+arrs[7]+"%\n");//刷新
recvText2.setText("气体浓度:"+arrs[5]+arrs[6]+arrs[7]+"% 良\n");
}
else if (arrs[0]=='2'&&arrs[5]>'3'){
//recvText2.append(arrs[5]+arrs[6]+arrs[7]+"%\n");//刷新
recvText2.setText("气体浓度:"+arrs[5]+arrs[6]+arrs[7]+"% 差,请通风\n");
}
//recvText.append("衣柜助手:"+recvMessageClient);//刷新
}
};
};
private String getInfoBuff(char[] buff,int count)
{
char[] temp = new char[count];
for (int i = 0; i < count; i++) {
temp[i]=buff[i];
}
return new String(temp);
}
}
2.这个是xml,温湿度和气体浓度初始值默认为0;当接收到单片机的发送过来的数据后,对应的数值会更新!
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
android:background="#99cccc"
tools:context=".MainActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="智能衣柜助手"
android:textSize="20dip" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/textView1">
<EditText
android:id="@+id/IPText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="请输入衣柜服务端的IP地址" />
<Button
android:id="@+id/StartConnect"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="开始连接" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</LinearLayout>
<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:id="@+id/textView" />
<Button
android:id="@+id/SendButtonClient"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="开" />
<Button
android:id="@+id/SendButtonClient1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="关" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="抽湿"
android:id="@+id/textView2" />
<Button
android:id="@+id/SendButtonClient2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="开" />
<Button
android:id="@+id/SendButtonClient3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="关" />
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/tv1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="22dip" />
</RelativeLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="温湿度:0℃ 0%"
android:id="@+id/textView3" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="气体浓度:0%"
android:id="@+id/textView4" />
</LinearLayout>
</RelativeLayout>
3.如果你很熟悉Android Studio的话,也可以直接使用我的全部源码!
4.关于APP的一些应该要优化的地方:
(1)逻辑:因为之前刚入门,所以可能在一些语句的逻辑上会有问题。但是不影响功能实现。
(2)当APP接收到单片机传过来的数据时,点击按钮会不灵敏,也就是说,点击按钮没有用,这是因为WiFi模块的接收函数已经被单片机那边占用了,不能同时再接收来自APP的数据,这个问题也困扰了我很久,我最后是在单片机那里把发送数据给APP的频率降低一点,改成每10秒发一次,就优化了这个问题,但是我现在还没有别的更好的办法去解决这个问题的根源,我也问过了老师,他也不知道…那就留给你们帮我想把,哈哈哈…
(3)界面太简陋,因为只有一个界面,所有功能都集成在一个界面了…
(4)暂时还没有增加用户和服务器数据库的功能,这些在后面的章节我会说。