I think I am fairly close to achieving what I need to, but I'm getting an error when trying to convert my current amplitude integer into a string in a textview.
So my aim is this: Display a camera preview (working), detect sound (possibly working) and display the current amplitude level of that sound in a textview (textPowerUp). Later I want to replace the textview with a counter that counts up when sound is detected, and slowly counts back down when it's not, but baby steps...
So no errors if I comment out the line:
txtPowerLevel.setText(Integer.toString(currentAmplitude));
But that's the line I'm -trying- to use to convert the amplitude integer into a string and insert it into my textview. And this line gives a null reference error.
I even tried to force the currentAmplitude to have a value of at least 0 with:
if (mRecorder.getMaxAmplitude() > 0) {
currentAmplitude = mRecorder.getMaxAmplitude();
} else {
currentAmplitude = 0;
}
But that doesn't seem to help. I still get a null reference error. I even tried setting the else to a value of '1' incase '0' was being seen as 'null' but no luck there either.
Here's the entire class... please let me know if you can spot the problem!
public class DBZPowerUp extends AppCompatActivity implements TextureView.SurfaceTextureListener {
MediaRecorder mRecorder = new MediaRecorder();
private Handler mHandler = new Handler();
private Camera mCamera;
private TextureView mTextureView;
private int currentAmplitude;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dbzpowerup);
// Variables for textureview
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
// Build the camera preview onto textureview
setContentView(mTextureView);
// Run methods to start audio capture
startAudioCapture();
getAmplitude();
// Repeat audio methods constantly
mHandler.postDelayed(runnable, 100);
// Input the current amplitude level into the power level textview
setCurrentAmplitude();
TextView txtPowerLevel = (TextView) findViewById(R.id.txtPowerLevel);
txtPowerLevel.setText(Integer.toString(currentAmplitude));
}
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mCamera = Camera.open();
try {
mCamera.setPreviewTexture(surface);
mCamera.startPreview();
} catch(IOException e) {
Log.e("DBZ_", "Camera broke");
}
mCamera.setDisplayOrientation(90);
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Ignored, Camera does all the work for us
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
stopAudioCapture();
mCamera.stopPreview();
mCamera.release();
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Invoked every time there's a new Camera preview frame
}
public void startAudioCapture() {
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
mRecorder.setOutputFile("/dev/null");
try {
mRecorder.prepare();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
mRecorder.start();
}
catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void stopAudioCapture() {
mRecorder.stop();
mRecorder.release();
}
public double getAmplitude() {
if (mRecorder != null)
return mRecorder.getMaxAmplitude();
else
return 0;
}
private Runnable runnable = new Runnable() {
@Override
public void run() {
/* do what you need to do */
getAmplitude();
/* and here comes the "trick" */
mHandler.postDelayed(this, 100);
}
};
private void setCurrentAmplitude() {
if (mRecorder.getMaxAmplitude() > 0) {
currentAmplitude = mRecorder.getMaxAmplitude();
} else {
currentAmplitude = 0;
}
}
}
And thanks so much in advanced!
Lee.
ANSWER (Thanks to Blackbelt):
I changed:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dbzpowerup);
// Variables for textureview
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
// Build the camera preview onto textureview
setContentView(mTextureView);
To:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dbzpowerup);
// Define the textureview in XML and apply the surface listener for camera preview
TextureView mTextureView = (TextureView) findViewById(R.id.textureView1);
mTextureView.setSurfaceTextureListener(this);
The problem of your NPE is due to
// Build the camera preview onto textureview
setContentView(mTextureView);
this way you are overriding he previous call to setContentView
which probably contains your TextView
. You could add the TextureView
to dbzpowerup.xml
and use findViewById
to grab a reference to it