当前位置: 首页 > news >正文

手机实现真随机数生成器

上次讲了通过传感器实现真随机算法,今天讲一下另外的方法:借助手机和平板硬件生成物理随机数,并且生成的数字无法预测,无法重复。方法是利用系统摄像头获取视频数据,再转换成随机数种子,同理也可以用麦克风进行录制音频数据作为种子。

package com.zwxuf.randomgenerator;import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.graphics.drawable.ColorDrawable;
import android.hardware.Camera;
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.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.media.MediaRecorder;
import android.os.Handler;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.WindowManager;import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;import androidx.annotation.NonNull;public class RandomGenerator implements TextureView.SurfaceTextureListener {private static final String TAG = "RandomGenerator";private Context mContext;private CameraDevice mCameraDevice;private ImageReader mImageReader;private CameraCaptureSession mCameraCaptureSession;private OnGenerateListener onGenerateListener;private boolean mStarting;private boolean mStopped;private CameraManager mCameraManager;private TextureView mTextureView;private Size mPreviewSize;private boolean mCanceled;public RandomGenerator(Context mContext) {this.mContext = mContext;mCameraManager = (CameraManager) mContext.getSystemService(Service.CAMERA_SERVICE);}public void start() {mTextureView.setSurfaceTextureListener(this);openCamera(mTextureView.getWidth(), mTextureView.getHeight());}@SuppressLint("MissingPermission")private void openCamera(int width, int height) {if (isStarting()) return;mStarting = true;mStopped = false;mCanceled = false;try {String cameraId = getMainCameraId(width, height);Log.i(TAG, "cameraId=" + cameraId);mCameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {@Overridepublic void onOpened(@NonNull CameraDevice camera) {mCameraDevice = camera;startPreview();}@Overridepublic void onDisconnected(@NonNull CameraDevice camera) {if (!mStopped) {assertTask("相机断开");}}@Overridepublic void onError(@NonNull CameraDevice camera, int error) {assertTask("打开相机失败,错误代码" + error);}}, null);} catch (Exception e) {Log.e(TAG, e.toString());assertTask("打开相机失败:" + e.toString());}}private String getMainCameraId(int width, int height) {String id = null;try {for (String cameraId : mCameraManager.getCameraIdList()) {CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);//默认打开后置摄像头if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT)continue;StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);mPreviewSize = getOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height);id = cameraId;break;}} catch (CameraAccessException e) {e.printStackTrace();}return id == null ? "0" : id;}/*** 从摄像头支持的预览Size中选择大于并且最接近width和height的size** @param sizeMap* @param width* @param height* @return*/private Size getOptimalSize(Size[] sizeMap, int width, int height) {List<Size> sizeList = new ArrayList<>();for (Size option : sizeMap) {//Dbg.print("系统支持的尺寸大小==width:" + option.getWidth() + " height:" + option.getHeight());if (width > height) {if (option.getWidth() > width && option.getHeight() > height) {sizeList.add(option);}} else {if (option.getWidth() > height && option.getHeight() > width) {sizeList.add(option);}}}if (sizeList.size() > 0) {return Collections.min(sizeList, new Comparator<Size>() {@Overridepublic int compare(Size lhs, Size rhs) {return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getWidth() * rhs.getHeight());}});}if (sizeList.size() > 0)return sizeList.get(0);return sizeMap[0];}private void startPreview() {try {SurfaceTexture mSurfaceTexture = mTextureView.getSurfaceTexture();mSurfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());Surface mSurface = new Surface(mSurfaceTexture);final CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);builder.addTarget(mSurface);mCameraDevice.createCaptureSession(Collections.singletonList(mSurface), new CameraCaptureSession.StateCallback() {@Overridepublic void onConfigured(@NonNull CameraCaptureSession session) {mCameraCaptureSession = session;try {session.setRepeatingRequest(builder.build(), mCaptureCallback, null); // 开始连续捕获图片} catch (CameraAccessException e) {e.printStackTrace();assertTask(null);}}@Overridepublic void onConfigureFailed(@NonNull CameraCaptureSession session) {assertTask(null);}}, null);} catch (Exception e) {e.printStackTrace();assertTask(null);}}private void release() {mStopped = true;if (mCameraCaptureSession != null) {mCameraCaptureSession.close();mCameraCaptureSession = null;}
//        try {
//            if (mImageReader != null) {
//                mImageReader.close();
//                mImageReader = null;
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }try {if (mCameraDevice != null) {mCameraDevice.close();mCameraDevice = null;}} catch (Exception e) {e.printStackTrace();}mStarting = false;}private void assertTask(String msg) {release();if (onGenerateListener != null) {onGenerateListener.onError(msg);}}public void stop() {if (!isStarting()) return;release();if (mCanceled) return;if (onGenerateListener == null) return;Bitmap bitmap = mTextureView.getBitmap();if (bitmap != null) {ByteArrayOutputStream out = new ByteArrayOutputStream();bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);byte[] data = out.toByteArray();long seed = makeRandomSeed(data);mTextureView.invalidate();if (onGenerateListener != null) {onGenerateListener.onSuccess(seed);}}}/*** 制作随机数种子* @param source* @return*/private long makeRandomSeed(byte[] source) {if (source == null || source.length == 0) {return 0;}try {MessageDigest digest = MessageDigest.getInstance("SHA-256");digest.update(source);byte[] hashBytes = digest.digest();BigInteger bi = new BigInteger(1, hashBytes);return bi.remainder(BigInteger.valueOf(Long.MAX_VALUE)).longValue(); //取余,也可以取中间8个字节} catch (Exception e) {e.printStackTrace();}return 0;}private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {};public void setOnGenerateListener(OnGenerateListener onGenerateListener) {this.onGenerateListener = onGenerateListener;}@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {Log.i(TAG, "onSurfaceTextureAvailable");openCamera(width, height);}@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}@Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {Log.i(TAG, "onSurfaceTextureDestroyed");assertTask(null);return false;}@Overridepublic void onSurfaceTextureUpdated(SurfaceTexture surface) {}public void cancel() {mCanceled = true;release();if (onGenerateListener != null) {onGenerateListener.onCancel();}}public boolean isCanceled() {return mCanceled;}public interface OnGenerateListener {void onSuccess(long seed);void onError(String msg);void onCancel();}public boolean isStarting() {return mStarting;}public void setTextureView(TextureView mTextureView) {this.mTextureView = mTextureView;}
}
package com.zwxuf.randomgenerator;import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;public class MainActivity extends AppCompatActivity implements View.OnTouchListener, RandomGenerator.OnGenerateListener {private static final String TAG = "RandomGenerator";private Button bn_generate;private RandomGenerator mGenerator;private TextureView mTextureView;private TextView tv_content;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mTextureView = findViewById(R.id.mTextureView);bn_generate = findViewById(R.id.bn_generate);tv_content = findViewById(R.id.tv_content);mGenerator = new RandomGenerator(this);mGenerator.setOnGenerateListener(this);mGenerator.setTextureView(mTextureView);bn_generate.setOnTouchListener(this);}@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {mTextureView.setVisibility(View.VISIBLE);tv_content.setVisibility(View.INVISIBLE);mGenerator.start();} else {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1000);}break;case MotionEvent.ACTION_MOVE:if (mGenerator.isCanceled()) return false;int x = (int) event.getX();int y = (int) event.getY();Rect localRect = new Rect();bn_generate.getLocalVisibleRect(localRect);if (!localRect.contains(x, y)) {mGenerator.cancel();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {bn_generate.releasePointerCapture();}}break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:mGenerator.stop();break;}return false;}@Overridepublic void onSuccess(long seed) {Log.i(TAG, "seed=" + seed);Toast.makeText(this, "" + seed, Toast.LENGTH_SHORT).show();mTextureView.setVisibility(View.INVISIBLE);tv_content.setVisibility(View.VISIBLE);//使用Random正常生成随机数Random random = new Random(seed);//例:生成五注双色球tv_content.setText(null);for (int i = 0; i < 5; i++) {String numbers = generateUnionLotto(random);tv_content.append(numbers);tv_content.append("\n");}}private String generateUnionLotto(Random random) {LinkedList<Integer> numbers = new LinkedList<>();for (int i = 0; i < 33; i++) {numbers.add(i + 1);}StringBuilder sb = new StringBuilder();int[] reds = new int[6];for (int i = 0; i < 6; i++) {int index = random.nextInt(numbers.size());reds[i] = numbers.get(index);numbers.remove(index);}int[] blues = new int[1];for (int i = 0; i < blues.length; i++) {blues[i] = random.nextInt(16) + 1;}Arrays.sort(reds);Arrays.sort(blues);for (int red : reds) {sb.append(String.format("%02d", red)).append(" ");}sb.append(" + ");for (int blue : blues) {sb.append(String.format("%02d", blue));}return sb.toString();}@Overridepublic void onError(String msg) {Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();}@Overridepublic void onCancel() {mTextureView.setVisibility(View.INVISIBLE);Toast.makeText(this, "取消", Toast.LENGTH_SHORT).show();}
}

http://www.dtcms.com/a/391650.html

相关文章:

  • 119.计数器产生中断(上升沿)计算方法,比如cnt[21:0],那么assign time = cnt[20]这样大致是多长时间产生一次中断
  • VSCode c/c++头文件函数点击无法跳转问题
  • `mysql_real_connect` 函数全面深度解析
  • 深入解析Yum元数据安全与Artifactory自动化原理
  • 第三章 强化学习助力优化
  • 使用角色和Ansible内容集合简化Playbook
  • 鸿蒙应用集成Push Kit 指南
  • 树莓派ubuntu20.04实现ROS noetic与Arduino通信
  • 【代码随想录算法训练营——Day17】二叉树——654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
  • 托福听力44
  • C++——STL
  • 「ECG信号处理——(25)基于ECG心率变异性(HRV)与EDA皮肤电活动的生理状态分析」2025年9月19日
  • 高通camx架构学习(四)——Camera Framework
  • 接口安全攻防战:从入门到精通的全方位防护指南
  • GEO(Generative Engine Optimization)技术详解与2025实践指南
  • Amazon SES 移出沙盒完整指南 高通过率模板
  • 从 IP over 鸽子到 TCP 的适应性
  • 大模型提示工程
  • 鸿蒙应用开发——Repeat组件的使用
  • 远程控制的全球节点功能如何开启?插件类型、并发数量怎么选?
  • 因果推断:因果回归树处理异质性处理效应(三)
  • 六应用层-真题
  • python笔记之正则篇(四)
  • 无标题文档
  • LeetCode 面试经典 150 题之验证回文串:双指针解题思路详解
  • pandas在AI中与其他库的协作
  • 【软件测试】第5章 测试分类(下)
  • 二物理层-真题-
  • c康复训练 01
  • MLP和CNN在图片识别中的对比——基于猫狗分类项目的实战分析