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

这是我全程参考的文章
参考文章
但中途还是有遇到一些文中没提到的问题,接下来逐一解决

一、硬件连接及原理

在这里插入图片描述淘宝上所买的开发板
在这里插入图片描述ESP32CAM原理图
在这里插入图片描述
电源端接5V
在这里插入图片描述
进行程序烧录的时候,将GPIO0与GND短接。
烧录完,运行开发板的时候再拔掉
在这里插入图片描述
TXD接USB的RXD,RXD接USB的TXD(即开发板的发送端接USB的接收端)

二、Arduino安装

链接:https://pan.baidu.com/s/1jc0FrE_oiNaGxl_j_R0Y-g
提取码:r8ul
复制这段内容后打开百度网盘手机App,操作更方便哦
在这里插入图片描述

三、arduino与esp32cam初使用

初步摄像头使用
可以根据这个教程,实现在PC端上显示摄像视频。

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

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

在这里插入图片描述
一个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 <WiFi.h>
// #include <U8g2lib.h>
#include <I2Cdev.h>
#include <Wire.h>
// #include <MPU6050.h>
#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程序,一杯奶茶钱,我把所有东西打包发你。

版权声明:本文为CSDN博主「momomomoy」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/timuxi/article/details/116099548

生成海报
点赞 0

momomomoy

我还没有学会写个人说明!

暂无评论

相关推荐

Arduino网络编程实战-WiFi篇-扫描网络

扫描网络 ESP-01/ESP-01 WiFi模块是由安信可科技开发,该模块核心处理器为ESP8266,在较小尺寸封装中集成了业界领先的Tensilica L06超低功耗32位微处理器(MCU),带有16位精简模式,主频支持80MHz和160

Arduino与Proteus仿真实例-DHT11温度湿度传感器驱动仿真

DHT11温度湿度传感器驱动仿真 DHT11 是一款基本的超低成本数字温度和湿度传感器。 它使用电容式湿度传感器和热敏电阻来测量周围的空气,并在数据引脚上吐出数字信号(不需要模拟输入引脚)。 它使用起来相当简单,但需要仔细定时来抓取数据。