android检测心率应用实例

丈夫志四海,万里犹比邻。这篇文章主要讲述android检测心率应用实例相关的知识,希望能为你提供帮助。
参考博客:https://blog.csdn.net/qq_36982160/article/details/81260273
参考github:https://github.com/ZhaoYukai/HeartRate
【android检测心率应用实例】如果运行时出现Program type already present: android.support.v4.app.BackStackRecord$Op错误,参考:https://stackoverflow.com/questions/49917614/program-type-already-present-android-support-v4-app-backstackrecordop
 
首先膜拜以上大神的博客和github,本人在引用上方github项目时出现了些问题,所以记下来以备以后用到。先讲下改错的过程:本人在Android Studio新建了项目后,就把github上的代码粘贴了过来,然后在manifests删掉以下内容:
< uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
然后把github项目中的HeartRate-master\\HeartRate-master\\libs路径里的jar包复制到了AS模块里的libs路径下(后面看来android-support-v4.jar包用不到),选中后右键添加到库。然后在模块级的build.gradle中修改compileSdkVersion、targetSdkVersion为27(https://www.jianshu.com/p/808e1d127a33)。然后修改了两个implementation 如下:
implementation \'com.android.support:appcompat-v7:27.1.1\'
implementation \'com.android.support:support-v4:27.1.1\'
然后修改MainActivity的几个地方如下:
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "DoNotDimScreen"); ====》
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "myapp:wakeLock");
然后在运行app前授权允许使用照相机后即可运行app
运行效果图:

android检测心率应用实例

文章图片

 
模块结构图:
android检测心率应用实例

文章图片

 
模块级的build.gradle:
1 apply plugin: \'com.android.application\' 2 3 android { 4compileSdkVersion 27 5 6 7 8defaultConfig { 9applicationId "com.mingrisoft.heartdetect" 10minSdkVersion 15 11targetSdkVersion 27 12versionCode 1 13versionName "1.0" 14 15testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 17} 18 19buildTypes { 20release { 21minifyEnabled false 22proguardFiles getDefaultProguardFile(\'proguard-android.txt\'), \'proguard-rules.pro\' 23} 24} 25 26 } 27 28 dependencies { 29implementation fileTree(include: [\'*.jar\'], dir: \'libs\') 30implementation \'com.android.support:appcompat-v7:27.1.1\' 31implementation \'com.android.support:support-v4:27.1.1\' 32implementation \'com.android.support.constraint:constraint-layout:1.1.3\' 33testImplementation \'junit:junit:4.12\' 34androidTestImplementation \'com.android.support.test:runner:1.0.2\' 35androidTestImplementation \'com.android.support.test.espresso:espresso-core:3.0.2\' 36implementation files(\'libs/achartengine-1.0.0.jar\') 37 }

 
manifests:

1 < ?xml version="1.0" encoding="utf-8"?> 2 < manifest xmlns:android="http://schemas.android.com/apk/res/android" 3package="com.mingrisoft.heartdetect"> 4 5< uses-permission android:name="android.permission.WAKE_LOCK" /> 6< uses-permission android:name="android.permission.CAMERA" /> 7< uses-feature android:name="android.hardware.camera" /> 8< uses-feature android:name="android.hardware.camera.autofocus" /> 9 10< application 11android:allowBackup="true" 12android:icon="@mipmap/ic_launcher" 13android:label="@string/app_name" 14android:roundIcon="@mipmap/ic_launcher_round" 15android:supportsRtl="true" 16android:theme="@style/AppTheme"> 17< activity android:name=".MainActivity"> 18< intent-filter> 19< action android:name="android.intent.action.MAIN" /> 20 21< category android:name="android.intent.category.LAUNCHER" /> 22< /intent-filter> 23< /activity> 24< /application> 25 26 < /manifest>

 
strings.xml:
1 < resources> 2< string name="app_name"> heartDetect< /string> 3< string name="hello_world"> Hello world!< /string> 4< string name="action_settings"> Settings< /string> 5< string name="show"> 显示< /string> 6 7 < /resources>

 
activity_main.xml:
1 < ?xml version="1.0" encoding="utf-8"?> 2 < LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3xmlns:app="http://schemas.android.com/apk/res-auto" 4xmlns:tools="http://schemas.android.com/tools" 5android:layout_width="match_parent" 6android:layout_height="match_parent" 7android:orientation="vertical" 8tools:context=".MainActivity"> 9 10< SurfaceView 11android:id="@+id/id_preview" 12android:layout_width="match_parent" 13android:layout_height="200dp" 14android:layout_marginLeft="50dp" 15android:layout_marginRight="50dp" /> 16 17< LinearLayout 18android:id="@+id/id_linearLayout_graph" 19android:layout_width="match_parent" 20android:layout_height="200dp" 21android:orientation="vertical" > 22< /LinearLayout> 23 24< TextView 25android:id="@+id/id_tv_heart_rate" 26android:layout_width="wrap_content" 27android:layout_height="wrap_content" 28android:layout_marginLeft="50dp" 29android:layout_weight="1" 30android:text="@string/show" > 31< /TextView> 32 33< TextView 34android:id="@+id/id_tv_Avg_Pixel_Values" 35android:layout_width="wrap_content" 36android:layout_height="wrap_content" 37android:layout_marginLeft="50dp" 38android:layout_weight="1" 39android:text="@string/show" > 40< /TextView> 41 42< TextView 43android:id="@+id/id_tv_pulse" 44android:layout_width="wrap_content" 45android:layout_height="wrap_content" 46android:layout_marginLeft="50dp" 47android:layout_weight="1" 48android:text="@string/show" > 49< /TextView> 50 51 52 < /LinearLayout >

 
ImageProcessing:

1 package com.mingrisoft.heartdetect; 2 3 /** 4* 图像处理类 5*/ 6 public abstract class ImageProcessing { 7 8/** 9* 内部调用的处理图片的方法 10*/ 11private static int decodeYUV420SPtoRedSum(byte[] yuv420sp , int width , int height) { 12if (yuv420sp == null) { 13return 0; 14} 15 16final int frameSize = width * height; 17int sum = 0; 18 19for (int j = 0 , yp = 0 ; j < height ; j++) { 20int uvp = frameSize + (j > > 1) * width; 21int u = 0; 22int v = 0; 23for (int i = 0 ; i < width ; i++, yp++) { 24int y = (0xff & ((int) yuv420sp[yp])) - 16; 25if (y < 0) { 26y = 0; 27} 28if ((i & 1) == 0) { 29v = (0xff & yuv420sp[uvp++]) - 128; 30u = (0xff & yuv420sp[uvp++]) - 128; 31} 32int y1192 = 1192 * y; 33int r = (y1192 + 1634 * v); 34int g = (y1192 - 833 * v - 400 * u); 35int b = (y1192 + 2066 * u); 36 37if (r < 0) { 38r = 0; 39} 40else if (r > 262143) { 41r = 262143; 42} 43 44if (g < 0) { 45g = 0; 46} 47else if (g > 262143) { 48g = 262143; 49} 50 51if (b < 0) { 52b = 0; 53} 54else if (b > 262143) { 55b = 262143; 56} 57 58int pixel = 0xff000000 | ((r < < 6) & 0xff0000) | ((g > > 2) & 0xff00) | ((b > > 10) & 0xff); 59int red = (pixel > > 16) & 0xff; 60sum += red; 61} 62} 63return sum; 64} 65 66/** 67* 对外开放的图像处理方法 68*/ 69public static int decodeYUV420SPtoRedAvg(byte[] yuv420sp , int width , int height) { 70if (yuv420sp == null) { 71return 0; 72} 73final int frameSize = width * height; 74int sum = decodeYUV420SPtoRedSum(yuv420sp, width, height); 75return (sum / frameSize); 76} 77 }

 
MainActivity:

1 package com.mingrisoft.heartdetect; 2 3 import android.app.Activity; 4 import android.content.Context; 5 import android.content.res.Configuration; 6 import android.graphics.Color; 7 import android.graphics.Paint.Align; 8 import android.hardware.Camera; 9 import android.hardware.Camera.PreviewCallback; 10 import android.os.Bundle; 11 import android.os.Handler; 12 import android.os.Message; 13 import android.os.PowerManager; 14 import android.os.PowerManager.WakeLock; 15 import android.util.Log; 16 import android.view.SurfaceHolder; 17 import android.view.SurfaceView; 18 import android.view.ViewGroup.LayoutParams; 19 import android.widget.LinearLayout; 20 import android.widget.TextView; 21 import android.widget.Toast; 22 23 import org.achartengine.ChartFactory; 24 import org.achartengine.GraphicalView; 25 import org.achartengine.chart.PointStyle; 26 import org.achartengine.model.XYMultipleSeriesDataset; 27 import org.achartengine.model.XYSeries; 28 import org.achartengine.renderer.XYMultipleSeriesRenderer; 29 import org.achartengine.renderer.XYSeriesRenderer; 30 31 import java.util.Timer; 32 import java.util.TimerTask; 33 import java.util.concurrent.atomic.AtomicBoolean; 34 35 /** 36* 程序的主入口 37*/ 38 public class MainActivity extends Activity { 39//曲线 40private Timer timer = new Timer(); 41//Timer任务,与Timer配套使用 42private TimerTask task; 43private static int gx; 44private static int j; 45 46private static double flag = 1; 47private Handler handler; 48private String title = "pulse"; 49private XYSeries series; 50private XYMultipleSeriesDataset mDataset; 51private GraphicalView chart; 52private XYMultipleSeriesRenderer renderer; 53private Context context; 54private int addX = -1; 55double addY; 56int[] xv = new int[300]; 57int[] yv = new int[300]; 58int[] hua=new int[]{9,10,11,12,13,14,13,12,11,10,9,8,7,6,7,8,9,10,11,10,10}; 59 60private static final AtomicBoolean processing = new AtomicBoolean(false); 61//Android手机预览控件 62private static SurfaceView preview = null; 63//预览设置信息 64private static SurfaceHolder previewHolder = null; 65//Android手机相机句柄 66private static Camera camera = null; 67//private static View image = null; 68private static TextView mTV_Heart_Rate = null; 69private static TextView mTV_Avg_Pixel_Values = null; 70private static TextView mTV_pulse = null; 71private static WakeLock wakeLock = null; 72private static int averageIndex = 0; 73private static final int averageArraySize = 4; 74private static final int[] averageArray = new int[averageArraySize]; 75 76/** 77* 类型枚举 78*/ 79public static enum TYPE { 80GREEN, RED 81}; 82 83//设置默认类型 84private static TYPE currentType = TYPE.GREEN; 85//获取当前类型 86public static TYPE getCurrent() { 87return currentType; 88} 89//心跳下标值 90private static int beatsIndex = 0; 91//心跳数组的大小 92private static final int beatsArraySize = 3; 93//心跳数组 94private static final int[] beatsArray = new int[beatsArraySize]; 95//心跳脉冲 96private static double beats = 0; 97//开始时间 98private static long startTime = 0; 99 100 101 102@Override 103public void onCreate(Bundle savedInstanceState) { 104super.onCreate(savedInstanceState); 105setContentView(R.layout.activity_main); //这里注意要改成自己的布局文件 106 107initConfig(); 108} 109 110/** 111* 初始化配置 112*/ 113@SuppressWarnings("deprecation") 114private void initConfig() { 115//曲线 116context = getApplicationContext(); 117 118//这里获得main界面上的布局,下面会把图表画在这个布局里面 119LinearLayout layout = (LinearLayout)findViewById(R.id.id_linearLayout_graph); 120 121//这个类用来放置曲线上的所有点,是一个点的集合,根据这些点画出曲线 122series = new XYSeries(title); 123 124//创建一个数据集的实例,这个数据集将被用来创建图表 125mDataset = new XYMultipleSeriesDataset(); 126 127//将点集添加到这个数据集中 128mDataset.addSeries(series); 129 130//以下都是曲线的样式和属性等等的设置,renderer相当于一个用来给图表做渲染的句柄 131int color = Color.GREEN; 132PointStyle style = PointStyle.CIRCLE; 133renderer = buildRenderer(color, style, true); 134 135//设置好图表的样式 136setChartSettings(renderer, "X", "Y", 0, 300, 4, 16, Color.WHITE, Color.WHITE); 137 138//生成图表 139chart = ChartFactory.getLineChartView(context, mDataset, renderer); 140 141//将图表添加到布局中去 142layout.addView(chart, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 143 144//这里的Handler实例将配合下面的Timer实例,完成定时更新图表的功能 145handler = new Handler() { 1

    推荐阅读