安卓使用网络摄像头扫码

网络摄像头,是一种可以通过网络发送视频数据的视频设备,与基于模拟信号的CCTV摄像头不同,我们可以在我们的应用中接受它的数字信号。

网络摄像头广泛用于监控。它们还可以用于库存管理,也可以用作Android平板电脑和自动售货机等设备的额外摄像头。

在本文中,我们将使用创建一个使用网络摄像头进行扫码的Android应用。使用ExoPlayer通过RTSP播放网络摄像头的视频流,Dynamsoft Barcode Reader用于识别条码。

新建项目

使用Android Studio创建一个空的activity的应用项目。

添加依赖项

  1. 在应用的build.gradle中添加ExoPlayer。

    groovy 复制代码
    implementation "androidx.media3:media3-exoplayer:1.4.1"
    implementation "androidx.media3:media3-exoplayer-dash:1.4.1"
    implementation "androidx.media3:media3-ui:1.4.1"
    implementation "androidx.media3:media3-exoplayer-rtsp:1.4.1"
  2. 添加Dynamsoft Barcode Reader。

    1. 打开settings.gradle添加Dynamsoft的maven仓库。

      groovy 复制代码
      dependencyResolutionManagement {
          repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
          repositories {
              google()
              mavenCentral()
              maven {
                  url "https://download2.dynamsoft.com/maven/aar"
              }
          }
      }
    2. 在应用的build.gradle中声明依赖。

      groovy 复制代码
      implementation 'com.dynamsoft:dynamsoftbarcodereaderbundle:10.4.2000'

添加权限

打开AndroidManifest.xml以添加Internet权限。

xml 复制代码
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

使用ExoPlayer播放网络摄像头的RTSP流

  1. 打开activity_main.xml,添加PlayerView。

    xml 复制代码
    <androidx.media3.ui.PlayerView
        android:id="@+id/playerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:surface_type="surface_view" >
    </androidx.media3.ui.PlayerView>

    MainActivity.java中,获取该视图。

    java 复制代码
    private PlayerView playerView;
    playerView = findViewById(R.id.playerView);
  2. 创建ExoPlayer的实例并将其设置为PlayerView的播放器。

    java 复制代码
    ExoPlayer player = new ExoPlayer.Builder(getApplicationContext()).build();
    playerView.setPlayer(player);
  3. 将RTSP流设置为播放器的媒体源。可以使用mediamtx启动一个本地RTSP服务器进行测试。

    java 复制代码
    protected Uri uri = Uri.parse("rtsp://192.168.8.65:8554/mystream");
    MediaSource mediaSource =
                 new RtspMediaSource.Factory()
                    .createMediaSource(MediaItem.fromUri(uri));
    player.setMediaSource(mediaSource);
  4. 准备播放器,并在准备就绪后进行播放。

    java 复制代码
    player.setPlayWhenReady(true);
    player.prepare();

从网络摄像头读取条码

  1. 初始化Dynamsoft Barcode Reader的许可证。可以在此处申请许可证

    java 复制代码
    LicenseManager.initLicense("DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==", this, (isSuccess, error) -> {
        if (!isSuccess) {
            error.printStackTrace();
        }
    });
  2. 创建capture vision router实例以调用Dynamsoft Barcode Reader来解码。

    java 复制代码
    private CaptureVisionRouter mRouter;
    mRouter = new CaptureVisionRouter(this);
  3. 启动一个计时器以捕获网络摄像头的视频帧并从中读取条形码。在TextView中显示结果。

    java 复制代码
    private boolean decoding = false;
    private boolean isVideoPlaying = false;
    private Timer timer = null;
    private void startDecoding(){
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                takePhotoAndDecode();
            }
        };
        timer = new Timer();
        timer.schedule(task, 1000,100);
    }
    
     @OptIn(markerClass = UnstableApi.class)
     @SuppressLint("NewApi")
     private void takePhotoAndDecode() {
        if (decoding == false && isVideoPlaying) {
            decoding = true;
            SurfaceView surfaceView = (SurfaceView) playerView.getVideoSurfaceView();
            // Create a bitmap the size of the scene view.
            final Bitmap bitmap = Bitmap.createBitmap(surfaceView.getWidth(), surfaceView.getHeight(),
                    Bitmap.Config.ARGB_8888);
            // Create a handler thread to offload the processing of the image.
            final HandlerThread handlerThread = new HandlerThread("PixelCopier");
            handlerThread.start();
            // Make the request to copy.
            PixelCopy.request(surfaceView, bitmap, (copyResult) -> {
                if (copyResult == PixelCopy.SUCCESS) {
                    CapturedResult result =  mRouter.capture(bitmap, EnumPresetTemplate.PT_READ_BARCODES);
                    DecodedBarcodesResult decodedBarcodesResult = result.getDecodedBarcodesResult();
                    if (decodedBarcodesResult != null) {
                        BarcodeResultItem[] items = decodedBarcodesResult.getItems();
                        StringBuilder sb = new StringBuilder();
                        for (BarcodeResultItem item:items) {
                            sb.append(item.getFormatString());
                            sb.append(": ");
                            sb.append(item.getText());
                            sb.append("\n");
                        }
                        runOnUiThread(new Runnable() {
                            public void run() {
                                textView.setText(sb.toString());
                            }
                        });
                    }
                }
                decoding = false;
                handlerThread.quitSafely();
            }, new Handler(handlerThread.getLooper()));
        }
    }
  4. 为播放器添加监听器来检查视频是否正在播放。

    java 复制代码
    player.addListener(
        new Player.Listener() {
            @Override
            public void onIsPlayingChanged(boolean isPlaying) {
                isVideoPlaying = isPlaying;
            }
        });

好了,我们已经完成了这个demo。

源代码

查看demo的源代码并尝试使用:

github.com/tony-xlh/IP...

相关推荐
李小白666 分钟前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp19 分钟前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶1 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
n北斗1 小时前
常用类晨考day15
java
骇客野人1 小时前
【JAVA】JAVA接口公共返回体ResponseData封装
java·开发语言
njnu@liyong1 小时前
图解HTTP-HTTP报文
网络协议·计算机网络·http
yuanbenshidiaos2 小时前
c++---------数据类型
java·jvm·c++
向宇it2 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
带电的小王2 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
Lojarro2 小时前
【Spring】Spring框架之-AOP
java·mysql·spring