Anthony Bonarrigo Anthony Bonarrigo - 7 months ago 87
Android Question

Android and ACRCloud: startRecording() called on an uninitialized AudioRecord

I am designing a simple app for music recognition using this SDK https://www.acrcloud.com/docs/audio-fingerprinting-sdks/android-sdk/

The demo provided by the SDK functions perfectly on my phone, target Android SDK is 18. I am currently developing this app on

minSdkVersion 19
and
targetSdkVersion 24
. Code wise, nothing is different from the demo except for the Activity's layout.

Here's my code:

import com.dd.CircularProgressButton;

import com.acrcloud.rec.sdk.ACRCloudConfig;
import com.acrcloud.rec.sdk.ACRCloudClient;
import com.acrcloud.rec.sdk.IACRCloudListener;
import com.acrcloud.rec.sdk.utils.ACRCloudLogger;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class MainActivity extends AppCompatActivity implements IACRCloudListener {

//Main recognition class and config objects
private ACRCloudClient mClient;
private ACRCloudConfig mConfig;

private TextView successOrFail;

private CircularProgressButton recognitionButton;

//recognition flags
private boolean mProcessing = false;
private boolean initState = false;

//path for local db, if necessary
//private String path = "";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);


recognitionButton = (CircularProgressButton) findViewById(R.id.startRecognition);
recognitionButton.setIndeterminateProgressMode(true);
recognitionButton.setText(R.string.rec_start);
recognitionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
start();
recognitionButton.setProgress(50);
}
});

final CircularProgressButton cancelButton = (CircularProgressButton) findViewById(R.id.stopRecogition);
cancelButton.setText(R.string.rec_cancel);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
cancel();
cancelButton.setProgress(-1);
}
});

successOrFail = (TextView) findViewById(R.id.successOrFailView);

//Configure ACRCloud
this.mConfig = new ACRCloudConfig();
this.mConfig.acrcloudListener = this;
this.mConfig.context = this;
this.mConfig.host = "xxxxxxxxxxxxxx";
this.mConfig.accessKey = "xxxxxxxxxxxxxxxx";
this.mConfig.accessSecret = "xxxxxxxxxxxxxxxx";
this.mConfig.reqMode = ACRCloudConfig.ACRCloudRecMode.REC_MODE_REMOTE;

this.mClient = new ACRCloudClient();

this.initState = this.mClient.initWithConfig(this.mConfig);
if (this.initState) {
this.mClient.startPreRecord(3000);
}
}


//Start recognition
public void start() {
if (!this.initState) {
Toast.makeText(this, "init error", Toast.LENGTH_SHORT).show();
return;
}

if (!mProcessing) {
mProcessing = true;
if (this.mClient == null || !this.mClient.startRecognize()) {
mProcessing = false;
//mResult.setText("start error!");
}
}
}

//recognition canceled
protected void cancel(){
if(mProcessing && this.mClient != null){
mProcessing = false;
this.mClient.cancel();
}
}


//handle result
@Override
public void onResult(String result) {
if (this.mClient != null) {
this.mClient.cancel();
mProcessing = false;
}


try {
JSONObject j = new JSONObject(result);
JSONObject j1 = j.getJSONObject("status");
int j2 = j1.getInt("code");
if(j2 == 0){
successOrFail.setVisibility(View.VISIBLE);
successOrFail.setText(R.string.success);
recognitionButton.setProgress(100);
}else{
successOrFail.setVisibility(View.VISIBLE);
successOrFail.setText(R.string.error);
recognitionButton.setProgress(0);
}
} catch (JSONException e) {
e.printStackTrace();
}
}

@Override
public void onVolumeChanged(double volume){

}


@Override
protected void onDestroy() {
super.onDestroy();
Log.e("MainActivity", "release");
if (this.mClient != null) {
this.mClient.release();
this.initState = false;
this.mClient = null;
}
}
}


and I am receiving this exception

08-31 16:38:20.119 29895-30448/musicmappr.abon219.com.musicmappr_prototype1 W/System.err: java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord.
08-31 16:38:20.119 29895-30448/musicmappr.abon219.com.musicmappr_prototype1 W/System.err: at android.media.AudioRecord.startRecording(AudioRecord.java:943)
08-31 16:38:20.119 29895-30448/musicmappr.abon219.com.musicmappr_prototype1 W/System.err: at com.acrcloud.rec.record.ACRCloudRecorder.startRecording(ACRCloudRecorder.java:64)
08-31 16:38:20.119 29895-30448/musicmappr.abon219.com.musicmappr_prototype1 W/System.err: at com.acrcloud.rec.sdk.worker.ACRCloudWorker.run(ACRCloudWorker.java:215)
08-31 16:38:20.139 29895-30448/musicmappr.abon219.com.musicmappr_prototype1 I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
08-31 16:38:20.139 29895-30448/musicmappr.abon219.com.musicmappr_prototype1 I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
08-31 16:38:21.789 29895-30448/musicmappr.abon219.com.musicmappr_prototype1 W/System.err: java.lang.IllegalStateException: stop() called on an uninitialized AudioRecord.
08-31 16:38:21.789 29895-30448/musicmappr.abon219.com.musicmappr_prototype1 W/System.err: at android.media.AudioRecord.stop(AudioRecord.java:996)
08-31 16:38:21.789 29895-30448/musicmappr.abon219.com.musicmappr_prototype1 W/System.err: at com.acrcloud.rec.record.ACRCloudRecorder.release(ACRCloudRecorder.java:133)
08-31 16:38:21.789 29895-30448/musicmappr.abon219.com.musicmappr_prototype1 W/System.err: at com.acrcloud.rec.sdk.worker.ACRCloudWorker.resumeRecognize(ACRCloudWorker.java:126)
08-31 16:38:21.789 29895-30448/musicmappr.abon219.com.musicmappr_prototype1 W/System.err: at com.acrcloud.rec.sdk.worker.ACRCloudWorker.run(ACRCloudWorker.java:222)


any advice on this issue would be greatly, greatly appreciated

Answer

Since no answers were provided, I'll provide my own input to help anyone using this SDK with this issue.

Beyond API level 23, you are REQUIRED to ask user for permissions. Adding the permission to the AndroidManifest isn't enough. The following code snippet is an example:

if(ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) ActivityCompat.requestPermissions(this, new String[{Manifest.permission.RECORD_AUDIO}, 1);