Как включить вспышку камеры Android на аудиозахвате с микрофона?
Следующий код работает. Он заставляет камеру мигать при любом звуке, захваченном микрофоном телефона Android. Работает на Samsung Galaxy S Duos. Все, что я хочу, это сделать его более стабильным из-за наличия потока.
package net.superlinux.concertlights;
import java.io.IOException;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
/**
* @author راني فايز أحمد
*
*/
public class FlashOnMicrophone extends Activity {
/* (non-Javadoc)
* @see android.app.Activity#onCreate(android.os.Bundle)
*/
// Toggle button that switches Camera-flash-to-blink on and off.
ToggleButton flash_on_microphone_toggleButton;
//SeekBar to set the microphone sensitivity level at which the flash will blink.
SeekBar seekBar;
//Camera Object
Camera camera;
/* Preparing a Thread to make the GUI seperate from Camera and Microphone.
Otherwise the phone will hang and freeze. */
Thread thread;
//mRecoder is the microphone object
MediaRecorder mRecorder;
//A flag used in the thread to turn on the flash blinking .
boolean isLightOn = false;
//sensitivity holds the minimum amplitude value at which the camera flash will blink
int sensitivity=0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// TODO Auto-generated method stub
setContentView(R.layout.flash_on_microphone);
flash_on_microphone_toggleButton = (ToggleButton) findViewById(R.id.flash_on_microphone_button);
seekBar=(SeekBar)findViewById(R.id.seekbar);
//SeekBar of sensitivity default is 1500.
seekBar.setProgress(1500); //default sensitivity value
//The following event listener sets the global variable 'sensitivity' so it can be taken by the thread.
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// TODO Auto-generated method stub
//There is a TextView not mentioned in the code here, but it's in the XML layout.
//We use this TextView to display the variable sensitivity
//We also set the current position of the SeekBar button as the sensitivity.
sensitivity=progress;
((TextView)findViewById(R.id.microphone_sensitivity_textview)).setText(getString(R.string.microphone_sensitivity_level)+"= "+sensitivity);
}
});
PackageManager pm = this.getPackageManager();
//The following makes sure that a camera exists. else warn the app user and quit the app.
if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Toast.makeText(this, "Device has no camera!",Toast.LENGTH_LONG).show();
finish();
return;
}
//Display has to be always unlocked to keep the flash light working.
getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
//Open the Camera, and get its parameters to set the camera settings.
camera = Camera.open();
final Parameters p = camera.getParameters();
//We open a thread , but will run it after defining the microphone.
thread = new Thread(new Runnable() {
@Override
public void run() {
//we make the thread running for ever.
// every time isLightOn is true , we blink the flash light.
// and turn on the flash light if the microphone amplitude exceeds the value of the variable 'sensitivity'
while(true){
while (isLightOn) {
try {
int volume_level = mRecorder.getMaxAmplitude();
if (volume_level>sensitivity){
Log.i("info", "torch is turn off!");
// make the flash off and the camera preview off too.
//we cannot reach the flash light device without the camera preview. both are attached to the other
p.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(p);
camera.stopPreview();
//now make the flash on and the camera preview on too.
Log.i("info", "torch is turn on!");
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
camera.startPreview();
//The camera preview will not work in this case because the on & off on the preview pameter is very fast
}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.i("info", "torch is turn off!");
e.printStackTrace();
}
}
}
}
});
/*
Prepare the audio capture source to be the microphone.
and save the audio in the file "/dev/null" .
This is a special file in Linux. Please know that Android is a Linux distribution.
This file acts like black hole in the space. You may also think of it as the dumpster of the unwanted and exiled data.
We, here , do not want to save the sound. All what we want is to sense it, and nothing else. so we throw it away in "/dev/null" .
*/
mRecorder= new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder. setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.setOutputFile("/dev/null");
try {
mRecorder.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//now turn on the microphone and the thread.
mRecorder.start();
thread.start();
//the event of turning on/off the flash-on-microphone sensing
flash_on_microphone_toggleButton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
//flip isLightOn between true and false.
isLightOn = !isLightOn;
}
});
}
@Override
public void onBackPressed() {
//clean up and activity shutdown.
mRecorder.stop();
thread.interrupt();
super.onBackPressed();
}
@Override
protected void onRestart() {
//re-run the camera on application minimize and maximize.
camera=Camera.open();
super.onRestart();
}
}