Android Studio + Esp32Cam 实现手机APP实时传输监控视频

前言

抱歉,当时写完这边博客,手机号就没用了,就没登陆过,后续我会整理完,放到github上的,有问题可以在github上交流.

参考文章

参考文章

步骤

1、硬件设备准备

Android Studio + Esp32Cam 实现手机APP实时传输监控视频_第1张图片

2、esp32-cam原理图

Android Studio + Esp32Cam 实现手机APP实时传输监控视频_第2张图片

3、设备接线

Android Studio + Esp32Cam 实现手机APP实时传输监控视频_第3张图片

4、Arduino安装

arduino下载地址
Android Studio + Esp32Cam 实现手机APP实时传输监控视频_第4张图片

5、arduino与esp32cam初使用

5.1 设置开发管理器网址

1)从Arduino IDE转到文件 > 首选项

2)在“其他Board Manager URL”字段中输入 https://www.arduino.cn/package_esp32_index.json,如下图所示。然后,单击“好”按钮。
Android Studio + Esp32Cam 实现手机APP实时传输监控视频_第5张图片

5.2 安装esp32

3)工具->开发板->开发板管理器
4)搜索esp32并安装
Android Studio + Esp32Cam 实现手机APP实时传输监控视频_第6张图片

5.3 选择 ESP32 Wrover Module

5)安装完成后
在工具->开发板 菜单中选择板子 在这选择了 ESP32 Wrover Module
Android Studio + Esp32Cam 实现手机APP实时传输监控视频_第7张图片

5.4 选择Huge App

Android Studio + Esp32Cam 实现手机APP实时传输监控视频_第8张图片

6、esp32-cam示例代码

6.1 打开示例代码

Android Studio + Esp32Cam 实现手机APP实时传输监控视频_第9张图片

6.2 将摄像头选择为安信可esp32-cam

未修改之前

//#define CAMERA_MODEL_AI_THINKER

修改后,去掉注释

#define CAMERA_MODEL_AI_THINKER

6.3 配置wifi

配置要连接的wifi

const char* ssid = “NETGEAR50”;
const char* password = “whua9307”;

6.4 编译烧录

下载代码时注意将esp32的IO0与GND相连
出现这个说明下载成功
Android Studio + Esp32Cam 实现手机APP实时传输监控视频_第10张图片

6.5 测试效果

  1. 将esp32的IO0与GND断开
  2. 打开串口助手
  3. 根据串口助手上提醒的ip信息,这里是 http://192.168.50.44
  4. 打开浏览器,输入该ip
    Android Studio + Esp32Cam 实现手机APP实时传输监控视频_第11张图片

七、利用Android Studio实现在手机APP内显示摄像视频

1.在layout层需要添加两个元件控件

Android Studio + Esp32Cam 实现手机APP实时传输监控视频_第12张图片
一个imageview 命名为img
一个button 命名为downloadFile

2.Acticity的代码

package xyz.pengzhihui.esp32ipcam;

import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public class MainActivity extends Activity implements View.OnClickListener
{

    private static final String TAG = "MainActivity::";

    private HandlerThread handlerThread;
    private Handler handler;
    private ImageView imageView;

    private final int DOWNDLOAD = 1;
    private final int REGISTER = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.downloadFile).setOnClickListener(this);
        imageView = findViewById(R.id.img);

        handlerThread = new HandlerThread("http");
        handlerThread.start();
        handler = new HttpHandler(handlerThread.getLooper());
    }


    @Override
    public void onClick(View v)
    {
        switch (v.getId())
        {
            case R.id.downloadFile:
                handler.sendEmptyMessage(DOWNDLOAD);
                break;
            default:
                break;
        }
    }

    //动态申请权限
    public static boolean isGrantExternalRW(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && activity.checkSelfPermission(
                Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

            activity.requestPermissions(new String[]{
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
            }, 1);
            return false;
        }
        return true;
    }


    private class HttpHandler extends Handler
    {
        public HttpHandler(Looper looper)
        {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg)
        {
            switch (msg.what)
            {
                case DOWNDLOAD:
                    downloadFile();
                    break;
                default:
                    break;
            }
        }
    }

    private void downloadFile()
    {
        String downloadUrl = "http://192.168.50.26:80/stream";
        String savePath = "/sdcard/pic.jpg";

        File file = new File(savePath);
        if (file.exists())
        {
            file.delete();
        }

        if(!isGrantExternalRW(this)){
            return;
        }

        BufferedInputStream bufferedInputStream = null;
        FileOutputStream outputStream = null;
        try
        {
            URL url = new URL(downloadUrl);

            try
            {
                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                httpURLConnection.setRequestMethod("GET");
                httpURLConnection.setConnectTimeout(1000 * 5);
                httpURLConnection.setReadTimeout(1000 * 5);
                httpURLConnection.setDoInput(true);
                httpURLConnection.connect();

                if (httpURLConnection.getResponseCode() == 200)
                {
                    InputStream in = httpURLConnection.getInputStream();

                    InputStreamReader isr = new InputStreamReader(in);
                    BufferedReader bufferedReader = new BufferedReader(isr);

                    String line;
                    StringBuffer stringBuffer = new StringBuffer();

                    int i = 0;

                    int len;
                    byte[] buffer;

                    while ((line = bufferedReader.readLine()) != null)
                    {
                        if (line.contains("Content-Type:"))
                        {
                            line = bufferedReader.readLine();

                            len = Integer.parseInt(line.split(":")[1].trim());

                            bufferedInputStream = new BufferedInputStream(in);
                            buffer = new byte[len];

                            int t = 0;
                            while (t < len)
                            {
                                t += bufferedInputStream.read(buffer, t, len - t);
                            }

                            bytesToImageFile(buffer, "0A.jpg");

                            final Bitmap bitmap = BitmapFactory.decodeFile("sdcard/0A.jpg");
                            runOnUiThread(new Runnable()
                            {
                                @Override
                                public void run()
                                {
                                    imageView.setImageBitmap(bitmap);
                                }
                            });
                        }


                    }
                }

            } catch (IOException e)
            {
                e.printStackTrace();
            }
        } catch (MalformedURLException e)
        {
            e.printStackTrace();
        } finally
        {
            try
            {
                if (bufferedInputStream != null)
                {
                    bufferedInputStream.close();
                }
                if (outputStream != null)
                {
                    outputStream.close();
                }
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }

    }

    private void bytesToImageFile(byte[] bytes, String fileName)
    {
        try
        {
            File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + fileName);
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(bytes, 0, bytes.length);
            fos.flush();
            fos.close();
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

}

3.需要烧录进Esp32Cam的代码

自己修改其中的局域网名和局域网密码,其他还有类似pins.h文件,需要从我开头所给的参考文章中获取。

#include 
// #include 
#include 
#include 
// #include 
#include "Pins.h"
#include "Camera.h"
#include "Motor.h"

const char* ssid = "";  //填你自己的局域网名
const char* password = ""; //局域网密码

WiFiServer server(81);

// OV2640 camera
Camera ov2640;

void setup()
{
	Serial.begin(115200);

	Wire.begin(I2C0_SDA, I2C0_SCL);
	Wire.setClock(400000);

	// while (!mpu6050.testConnection());
	// mpu6050.initialize();

	ov2640.initialize();

	int n = WiFi.scanNetworks();
	Serial.println("scan done");
	if (n == 0)
	{
		Serial.println("no networks found");
	}
	else
	{
		Serial.print(n);
		Serial.println(" networks found");
		for (int i = 0; i < n; ++i)
		{
			// Print SSID and RSSI for each network found
			Serial.print(i + 1);
			Serial.print(": ");
			Serial.print(WiFi.SSID(i));
			Serial.print(" (");
			Serial.print(WiFi.RSSI(i));
			Serial.print(")");
			Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
			delay(10);
		}
	}

	WiFi.begin(ssid, password);

	while (WiFi.status() != WL_CONNECTED)
	{
		delay(500);
		Serial.print(".");
	}
	Serial.println("");
	Serial.println("WiFi connected");

	ov2640.startCameraServer();

	Serial.print("Camera Ready! Use 'http://");
	Serial.print(WiFi.localIP());
	Serial.println("' to connect");

	server.begin();
}


float i = -1;
long heart_beat = 0;
void loop()
{

	Serial.println(analogRead(38));

	WiFiClient client = server.available();   // listen for incoming clients
	if (client)
	{
		// if you get a client,
		Serial.println("New Client.");           // print a message out the serial port
		String currentLine = "";                // make a String to hold incoming data from the client
		while (client.connected())
		{            // loop while the client's connected
			if (client.available())
			{             // if there's bytes to read from the client,
		
			}
		}
	}

	delay(50);
}
String getValue(String data, char separator, int index)
{
	int found = 0;
	int strIndex[] = { 0, -1 };
	int maxIndex = data.length() - 1;

	for (int i = 0; i <= maxIndex && found <= index; i++)
	{
		if (data.charAt(i) == separator || i == maxIndex)
		{
			found++;
			strIndex[0] = strIndex[1] + 1;
			strIndex[1] = (i == maxIndex) ? i + 1 : i;
		}
	}
	return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

4.注意事项

1.关于I2Cdev.h文件可能在烧录的时候没有这个库,这个需要自行去github上下载对应的库,并导入就能正常编译了
icdev库下载

2.如果要在手机APP模拟器上连上网就需要在文件AndroidManifest.xml 加上
android:supportsRtl=“true”

3.需要在文件AndroidManifest.xml 加上android:requestLegacyExternalStorage = “true” 这个属性

android 10 系统获取图片权限问题

Last: 如果你实在很懒,想不动脑就直接获得能运行的APP程序,一杯奶茶钱,我把所有东西打包发你。

你可能感兴趣的:(arduino,android,studio,物联网,wifi)