Android 测试环境噪音分贝
前言:
*近做工具类项目,手机上小工具各种,有一个测量环境噪音分贝值的,个人对机车码表式显示忠爱(有点机车情节),网上和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 图档上传。
————————————————