基于语音控制的智能衣柜系统——安卓手机APP的实现

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)暂时还没有增加用户和服务器数据库的功能,这些在后面的章节我会说。

上一篇:明天直播:datop——用在冷热内存识别和跨 numa 访存有多优秀?


下一篇:元旦了,送给程序员的祝福礼!!