Android测试环境噪音分贝
S三杯两盏淡酒 人气:0前言:
最近做工具类项目,手机上小工具各种,有一个测量环境噪音分贝值的,个人对机车码表式显示忠爱(有点机车情节),网上和Android APP market 转了一圈尽没发现让人心动了。所以只能自己动手,做图,做定义控件去实现。
具体实现如下:
素材准备:
自定义控件 xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:orientation="vertical"> <ImageView android:id="@+id/panel" android:layout_width="300dp" android:layout_height="300dp" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:scaleType="fitCenter" android:src="@drawable/panel__green" /> <ImageView android:id="@+id/pointer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerInParent="true" android:layout_gravity="center_horizontal" android:alpha="0.8" android:scaleType="centerInside" android:src="@drawable/pointer" /> <LinearLayout android:layout_centerHorizontal="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="50dp" android:layout_centerVertical="true"> <TextView android:id="@+id/value" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="welcome to use Nosy test !" /> <TextView android:id="@+id/maxvalue" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:paddingLeft="20dp" android:text="MAX:" /> </LinearLayout> </RelativeLayout>
自定义控件类:核心思路其实就是对ImageView 图片的旋转
public class PlateView extends RelativeLayout { public void setmMaxValue(double mMaxValue) { this.mMaxValue = mMaxValue; } private double mMaxValue =0; private ImageView mPanel; private ImageView mPointer; private TextView textView; private TextView maxTextView; private Matrix matrix = new Matrix(); private Context mContext; private double mLastValue = 50; public double getValue() { return value; } public void setValue(double value) { mLastValue = this.value; this.value = value; if(Math.abs(mMaxValue)<Math.abs(this.value)){ mMaxValue = this.value; } show(); } private double value = 50; public PlateView(Context context) { super(context); } public PlateView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; LayoutInflater layoutInflater = (LayoutInflater) context. getSystemService(Context.LAYOUT_INFLATER_SERVICE); layoutInflater.inflate(R.layout.plate, this); mPanel = (ImageView) findViewById(R.id.panel); mPointer = (ImageView) findViewById(R.id.pointer); textView=(TextView) findViewById(R.id.value); maxTextView=(TextView) findViewById(R.id.maxvalue); show(); } public void show() { float rotate = (float) (getValue() - this.mLastValue); if (Math.abs(rotate) > 0.1) { mPointer.setScaleType(ImageView.ScaleType.MATRIX); //required matrix.postRotate(rotate*8/5, mPointer.getWidth() / 2, mPointer.getHeight() / 2); mPointer.setImageMatrix(matrix); textView.setText(getValueText(getValue())); maxTextView.setText("MAX:"+getValueText(this.mMaxValue)); invalidate(); requestLayout(); } } private String getValueText(double value){ value+=0.0000001; String sRes =value+""; if(sRes.contains(".")){ sRes = sRes.substring(0,sRes.indexOf(".")+3); } return sRes; } public int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } }
分贝测量类:
public class AudioRecordDemo { private static final String TAG = "AudioRecord"; static final int SAMPLE_RATE_IN_HZ = 8000; static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ, AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT); AudioRecord mAudioRecord; boolean isGetVoiceRun; Object mLock; private WeakReference<MainActivity> mActivity; public AudioRecordDemo(MainActivity activity) { mLock = new Object(); mActivity = new WeakReference<>(activity); } public void sotp() { this.isGetVoiceRun = false; } public void getNoiseLevel() { if (isGetVoiceRun) { return; } mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE_IN_HZ, AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT, BUFFER_SIZE); if (mAudioRecord == null) { } isGetVoiceRun = true; new Thread(new Runnable() { @Override public void run() { mAudioRecord.startRecording(); short[] buffer = new short[BUFFER_SIZE]; final MainActivity activity = mActivity.get(); while (isGetVoiceRun) { int r = mAudioRecord.read(buffer, 0, BUFFER_SIZE); long v = 0; for (int i = 0; i < buffer.length; i++) { v += buffer[i] * buffer[i]; } double mean = v / (double) r; final double volume = 10 * Math.log10(mean); Log.d(TAG, "db value:" + volume); if (null != activity) { activity.runOnUiThread(new Runnable() { @Override public void run() { activity.plateView.setValue(volume); } }); } // 大概一秒十次 synchronized (mLock) { try { mLock.wait(100); } catch (InterruptedException e) { e.printStackTrace(); } } } mAudioRecord.stop(); mAudioRecord.release(); mAudioRecord = null; if (null != activity) { activity.runOnUiThread(new Runnable() { @Override public void run() { activity.plateView.setmMaxValue(0); activity.plateView.setValue(1); } }); } } }).start(); } }
记得加入Manifest 权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Layout使用控件:
<com.asus.function.antitouch.sound.PlateView android:id="@+id/soundplate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/start"/>
Activity中代码:
audioRecordDemo = new AudioRecordDemo(this); plateView = (PlateView) findViewById(R.id.soundplate); start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (start.getText().toString().equalsIgnoreCase(STOP)) { audioRecordDemo.sotp(); start.setText(START); } else { audioRecordDemo.getNoiseLevel(); start.setText(STOP); } } }); }
APP 效果图:
结语:
图片素材质量差了些,但效果算达到预期,由于声音分贝值本身变化是线性的,所以即使这里我没有加入动画效果,指针的转动线性也是令人可以接受的。另外可惜没做好gif 图档上传。
加载全部内容