微信虚拟视频插件安卓,微信虚拟相机替换拍照,java源码分享

简介: 完整的相机应用项目包含三个主要文件:主活动实现、布局文件和清单文件。代码实现了相机预览、

下载地址:http://m.pan38.com/download.php?code=BWQJMR 提取码:6666
完整的相机应用项目包含三个主要文件:主活动实现、布局文件和清单文件。代码实现了相机预览、拍照、自动对焦、图像保存等功能

package com.example.advancedcamera;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
import android.media.ImageReader;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CAMERA_PERMISSION = 1;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

static {
    ORIENTATIONS.append(Surface.ROTATION_0, 90);
    ORIENTATIONS.append(Surface.ROTATION_90, 0);
    ORIENTATIONS.append(Surface.ROTATION_180, 270);
    ORIENTATIONS.append(Surface.ROTATION_270, 180);
}

private TextureView textureView;
private Button captureButton;
private String cameraId;
private CameraDevice cameraDevice;
private CameraCaptureSession captureSession;
private CaptureRequest.Builder previewRequestBuilder;
private CaptureRequest previewRequest;
private Size previewSize;
private ImageReader imageReader;
private Handler backgroundHandler;
private HandlerThread backgroundThread;
private File outputFile;
private Semaphore cameraOpenCloseLock = new Semaphore(1);
private Integer sensorOrientation;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    textureView = findViewById(R.id.texture);
    captureButton = findViewById(R.id.capture);

    captureButton.setOnClickListener(v -> {
        lockFocus();
    });
}

@Override
protected void onResume() {
    super.onResume();
    startBackgroundThread();

    if (textureView.isAvailable()) {
        openCamera(textureView.getWidth(), textureView.getHeight());
    } else {
        textureView.setSurfaceTextureListener(surfaceTextureListener);
    }
}

@Override
protected void onPause() {
    closeCamera();
    stopBackgroundThread();
    super.onPause();
}

private void startBackgroundThread() {
    backgroundThread = new HandlerThread("CameraBackground");
    backgroundThread.start();
    backgroundHandler = new Handler(backgroundThread.getLooper());
}

private void stopBackgroundThread() {
    backgroundThread.quitSafely();
    try {
        backgroundThread.join();
        backgroundThread = null;
        backgroundHandler = null;
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

private final TextureView.SurfaceTextureListener surfaceTextureListener = new TextureView.SurfaceTextureListener() {
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
        openCamera(width, height);
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
        configureTransform(width, height);
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture texture) {
    }
};

private void openCamera(int width, int height) {
    CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try {
        cameraId = manager.getCameraIdList()[0];
        CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
        StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);

        previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height);

        int orientation = getResources().getConfiguration().orientation;
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            textureView.setAspectRatio(previewSize.getWidth(), previewSize.getHeight());
        } else {
            textureView.setAspectRatio(previewSize.getHeight(), previewSize.getWidth());
        }

        configureTransform(width, height);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
            return;
        }

        manager.openCamera(cameraId, stateCallback, backgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private Size chooseOptimalSize(Size[] choices, int width, int height) {
    List<Size> bigEnough = new ArrayList<>();
    int w = width;
    int h = height;

    for (Size option : choices) {
        if (option.getHeight() == option.getWidth() * h / w && 
            option.getWidth() >= width && option.getHeight() >= height) {
            bigEnough.add(option);
        }
    }

    if (bigEnough.size() > 0) {
        return Collections.min(bigEnough, new CompareSizesByArea());
    } else {
        return choices[0];
    }
}

static class CompareSizesByArea implements Comparator<Size> {
    @Override
    public int compare(Size lhs, Size rhs) {
        return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());
    }
}

private void configureTransform(int viewWidth, int viewHeight) {
    if (textureView == null || previewSize == null) {
        return;
    }

    int rotation = getWindowManager().getDefaultDisplay().getRotation();
    Matrix matrix = new Matrix();
    RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
    RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
    float centerX = viewRect.centerX();
    float centerY = viewRect.centerY();

    if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
        bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
        matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
        float scale = Math.max(
            (float) viewHeight / previewSize.getHeight(),
            (float) viewWidth / previewSize.getWidth());
        matrix.postScale(scale, scale, centerX, centerY);
        matrix.postRotate(90 * (rotation - 2), centerX, centerY);
    }

    textureView.setTransform(matrix);
}

private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
    @Override
    public void onOpened(@NonNull CameraDevice camera) {
        cameraOpenCloseLock.release();
        cameraDevice = camera;
        createCameraPreviewSession();
    }

    @Override
    public void onDisconnected(@NonNull CameraDevice camera) {
        cameraOpenCloseLock.release();
        camera.close();
        cameraDevice = null;
    }

    @Override
    public void onError(@NonNull CameraDevice camera, int error) {
        cameraOpenCloseLock.release();
        camera.close();
        cameraDevice = null;
        finish();
    }
};

private void createCameraPreviewSession() {
    try {
        SurfaceTexture texture = textureView.getSurfaceTexture();
        texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
        Surface surface = new Surface(texture);

        previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        previewRequestBuilder.addTarget(surface);

        cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(@NonNull CameraCaptureSession session) {
                if (cameraDevice == null) {
                    return;
                }

                captureSession = session;
                try {
                    previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                    previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

                    previewRequest = previewRequestBuilder.build();
                    captureSession.setRepeatingRequest(previewRequest, captureCallback, backgroundHandler);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                Toast.makeText(MainActivity.this, "Failed to configure camera", Toast.LENGTH_SHORT).show();
            }
        }, backgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private void lockFocus() {
    try {
        previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
        captureSession.capture(previewRequestBuilder.build(), captureCallback, backgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private void captureStillPicture() {
    try {
        if (cameraDevice == null) return;

        final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        captureBuilder.addTarget(imageReader.getSurface());

        captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
        captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));

        CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                unlockFocus();
            }
        };

        captureSession.stopRepeating();
        captureSession.capture(captureBuilder.build(), captureCallback, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private void unlockFocus() {
    try {
        previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
        previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
        captureSession.capture(previewRequestBuilder.build(), captureCallback, backgroundHandler);

        previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
        captureSession.setRepeatingRequest(previewRequestBuilder.build(), captureCallback, backgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private final CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
    @Override
    public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
        process(partialResult);
    }

    @Override
    public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
        process(result);
    }

    private void process(CaptureResult result) {
        switch (state) {
            case STATE_PREVIEW:
                break;
            case STATE_WAITING_LOCK:
                Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
                if (afState == null) {
                    captureStillPicture();
                } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState || 
                           CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
                    Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                    if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                        state = STATE_PICTURE_TAKEN;
                        captureStillPicture();
                    } else {
                        runPrecaptureSequence();
                    }
                }
                break;
            case STATE_WAITING_PRECAPTURE:
                Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE || 
                    aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
                    state = STATE_WAITING_NON_PRECAPTURE;
                }
                break;
            case STATE_WAITING_NON_PRECAPTURE:
                Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
                    state = STATE_PICTURE_TAKEN;
                    captureStillPicture();
                }
                break;
        }
    }
};

private void runPrecaptureSequence() {
    try {
        previewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
        state = STATE_WAITING_PRECAPTURE;
        captureSession.capture(previewRequestBuilder.build(), captureCallback, backgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private void closeCamera() {
    try {
        cameraOpenCloseLock.acquire();
        if (captureSession != null) {
            captureSession.close();
            captureSession = null;
        }
        if (cameraDevice != null) {
            cameraDevice.close();
            cameraDevice = null;
        }
        if (imageReader != null) {
            imageReader.close();
            imageReader = null;
        }
    } catch (InterruptedException e) {
        throw new RuntimeException("Interrupted while trying to lock camera closing.");
    } finally {
        cameraOpenCloseLock.release();
    }
}

private static class ImageSaver implements Runnable {
    private final Image image;
    private final File file;

    ImageSaver(Image image, File file) {
        this.image = image;
        this.file = file;
    }

    @Override
    public void run() {
        ByteBuffer buffer = image.getPlanes()[0].getBuffer();
        byte[] bytes = new byte[buffer.remaining()];
        buffer.get(bytes);
        FileOutputStream output = null;
        try {
            output = new FileOutputStream(file);
            output.write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            image.close();
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

}

xml version="1.0" encoding="utf-8"?>

















相关文章
|
5月前
|
Java 数据安全/隐私保护 计算机视觉
手机虚拟视频替换摄像头,QQ微信虚拟视频插件,jar代码分享
这段代码演示了如何使用JavaCV捕获视频流、处理帧数据并输出到虚拟摄像头设备。它需要JavaCV和OpenCV库支持
|
5月前
|
Shell 数据安全/隐私保护 Python
微信虚拟摄像头插件,QQ虚拟相机拍摄录像工具,替换虚拟视频聊天软件
完整的虚拟摄像头实现方案,包含多个模块的代码实现。这个项目可以模拟摄像头设备,并在微信/QQ视频
|
3月前
|
消息中间件 人工智能 Java
抖音微信爆款小游戏大全:免费休闲/竞技/益智/PHP+Java全筏开源开发
本文基于2025年最新行业数据,深入解析抖音/微信爆款小游戏的开发逻辑,重点讲解PHP+Java双引擎架构实战,涵盖技术选型、架构设计、性能优化与开源生态,提供完整开源工具链,助力开发者从理论到落地打造高留存、高并发的小游戏产品。
|
3月前
|
缓存 小程序 前端开发
商城/点餐/家政类小程序源码合集_微信抖音小程序源码开发从入门到精通实战
本文系统讲解如何利用现有源码快速开发商城、点餐、家政类微信/抖音小程序,涵盖环境搭建、核心功能实现、多平台部署与优化,提供完整技术方案。实战导向,助力开发者高效入门与落地。
|
3月前
|
小程序 PHP 图形学
热门小游戏源码(Python+PHP)下载-微信小程序游戏源码Unity发实战指南​
本文详解如何结合Python、PHP与Unity开发并部署小游戏至微信小程序。涵盖技术选型、Pygame实战、PHP后端对接、Unity转换适配及性能优化,提供从原型到发布的完整指南,助力开发者快速上手并发布游戏。
|
3月前
|
存储 小程序 Java
热门小程序源码合集:微信抖音小程序源码支持PHP/Java/uni-app完整项目实践指南
小程序已成为企业获客与开发者创业的重要载体。本文详解PHP、Java、uni-app三大技术栈在电商、工具、服务类小程序中的源码应用,提供从开发到部署的全流程指南,并分享选型避坑与商业化落地策略,助力开发者高效构建稳定可扩展项目。
|
5月前
|
API 数据安全/隐私保护 开发者
企业微信自动加好友软件,导入手机号批量添加微信好友,python版本源码分享
代码展示了企业微信官方API的合规使用方式,包括获取access_token、查询部门列表和创建用户等功能
|
5月前
|
Android开发 数据安全/隐私保护
手机微信虚拟视频聊天,安卓免root虚拟摄像头,免root虚拟hook相机
以上代码实现了一个完整的免root虚拟摄像头方案,通过Hook系统摄像头服务和微信视频通话接口
|
5月前
|
Java 计算机视觉
微信虚拟视频聊天插件,QQ抖音快手虚拟摄像头工具,替换相机视频流java
实现包含了虚拟摄像头核心功能,可以捕获真实摄像头视频流,处理后输出到虚拟摄像头设备。
微信qq陌陌soul,虚拟视频聊天插件,xposed摄像头替换工具
包含三个核心模块:虚拟摄像头服务、视频处理引擎和Xposed框架集成。

热门文章

最新文章