My app is crashing every time I try to click the start button. I am getting the "play() called on uninitialized AudioTrack" but the audioTrack is initialized. I've tried other solutions to the problem but I can't seem to find my own solution.
Complete stack trace:
FATAL EXCEPTION: main
Process: com.example.recorder, PID: 5010
java.lang.IllegalStateException: Could not execute method for android:onClick
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
at android.view.View.performClick(View.java:6600)
at android.view.View.performClickInternal(View.java:6577)
at android.view.View.access$3100(View.java:781)
at android.view.View$PerformClick.run(View.java:25912)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6923)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:870)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:6600)
at android.view.View.performClickInternal(View.java:6577)
at android.view.View.access$3100(View.java:781)
at android.view.View$PerformClick.run(View.java:25912)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6923)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:870)
Caused by: java.lang.IllegalStateException: play() called on uninitialized AudioTrack.
at android.media.AudioTrack.play(AudioTrack.java:2074)
at com.example.recorder.MainActivity.start(MainActivity.java:93)
at com.example.recorder.MainActivity.requestAudioPermissions(MainActivity.java:152)
at com.example.recorder.MainActivity.startRecording(MainActivity.java:49)
MainActivity:
private int freq =44100;//frequencia de amostragem
private AudioRecord audioRecord = null;//variavel para gravação
private Thread Rthread = null;
//private AudioManager audioManager=null;
private AudioTrack audioTrack=null;//variavel para play
//byte[] buffer = new byte[freq];
public static final String LOG_TAG = "YOUR-TAG-NAME";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//função com chamada as permissões nescessárias para captação e execução de áudio pelo celular
public void startRecording(View view) {
requestAudioPermissions();
}
protected void start() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
final int bufferSizeIn = AudioRecord.getMinBufferSize(freq, //buffer
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
final int bufferSizeOut = AudioTrack.getMinBufferSize(freq, //buffer
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT);
//configurando as variaveis que serão utilizadas para captação e reprodução do áudio
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, freq,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSizeIn);
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, freq,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSizeOut,
AudioTrack.MODE_STATIC);
//audioTrack.setPlaybackRate(freq);
final byte[] bufferIn = new byte[bufferSizeIn];
final byte[] bufferOut = new byte[bufferSizeOut];
audioRecord.startRecording(); //começa a captar a voz
Log.i(LOG_TAG, "Audio Recording started");
audioTrack.play(); //começa a transmitir a voz
Log.i(LOG_TAG, "Audio Playing started");
Rthread = new Thread(new Runnable() {
public void run() {
while (true) {
try {
audioRecord.read(bufferIn, 0, bufferSizeIn);
audioTrack.write(bufferOut, 0, bufferSizeOut);
} catch (Throwable t) {
Log.e("Error", "Read write failed");
t.printStackTrace();
}
}
}
});
Rthread.start();
}
public void stopRecording(View view) {
if(audioRecord!=null){
audioRecord.stop();
}
}
//Requesting run-time permissions
//Create placeholder for user's consent to record_audio permission.
//This will be used in handling callback
private final int MY_PERMISSIONS_RECORD_AUDIO = 1;
private void requestAudioPermissions() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
//When permission is not granted by user, show them message why this permission is needed.
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.RECORD_AUDIO)) {
Toast.makeText(this, "Please grant permissions to record audio", Toast.LENGTH_LONG).show();
//Give user option to still opt-in the permissions
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.RECORD_AUDIO},
MY_PERMISSIONS_RECORD_AUDIO);
} else {
// Show user dialog to grant permission to record audio
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.RECORD_AUDIO},
MY_PERMISSIONS_RECORD_AUDIO);
}
}
//If permission is granted, then go ahead recording audio
else if (ContextCompat.checkSelfPermission(this,
Manifest.permission.RECORD_AUDIO)
== PackageManager.PERMISSION_GRANTED) {
//Go ahead with recording audio now
start();
}
}
//Handling callback
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_RECORD_AUDIO: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay!
start();
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "Permissions Denied to record audio", Toast.LENGTH_LONG).show();
}
return;
}
}
}
activity_main:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Aperte Start para começar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.503"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.274" />
<Button
android:id="@+id/btnStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="116dp"
android:layout_marginLeft="116dp"
android:layout_marginTop="188dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="116dp"
android:onClick="startRecording"
android:text="Start"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="116dp"
android:layout_marginTop="28dp"
android:layout_marginEnd="116dp"
android:layout_marginRight="116dp"
android:onClick="stopRecording"
android:text="Stop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnStart" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="20dp" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="20dp" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top" />
AndroidManifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.recorder">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Can't find what is wrong.