I am currently using AudioTrack in stream mode to play some prerecorded tracks. Play and stop mechanics work properly.However, when i hit pause and try to resume afterwards the buffer only reads -1, indicating that the EOF was reached.
I tried to mark and reset the Inputstream, like it's suggested in some posts but it didn't help.
public void pauseTrack() {
currentAudioTrack.pause();
isPaused = true;
}
public void resumeTrack() {
isPaused = false;
}
#Override public void run() {
try {
while (offset < audioFile.length()) {
if (isPaused)
continue;
currentAudioTrack.play();
int numberOfBytesRead = fileInputStream.read(audioData);
if (numberOfBytesRead != -1) {
currentAudioTrack.write(audioData, 0, numberOfBytesRead);
offset+=numberOfBytesRead;
}
else {
return;
}
}
Log.v("status", "finished reading");
} catch (IOException io) {
Log.v("Exception", "IOException found: " + io.getLocalizedMessage());
} catch (IllegalStateException ie) {
Log.v("Exception","IllegalStateException:" + ie.getLocalizedMessage());
}
}
What am i doing wrong?
Just to give some closure to the post, i ended up changing to the AudioTrack static mode. The change wasn't because of the pause situation, however it end up solving it. Since the buffer writing is done all in one take, it doesn't present the challenges of the stream mode.
Try this
public void pauseTrack()
{
currentAudioTrack.pause();
isPaused = true;
}
public void resumeTrack()
{
isPaused = false;
}
#Override public void run()
{
try {
while (offset < audioFile.length())
{
if(isPaused != true)
{
currentAudioTrack.play();
int numberOfBytesRead = fileInputStream.read(audioData);
if (numberOfBytesRead != -1) {
currentAudioTrack.write(audioData, 0, numberOfBytesRead);
offset+=numberOfBytesRead;
}
else {
return;
}
}
}
Log.v("status", "finished reading");
} catch (IOException io) {
Log.v("Exception", "IOException found: " + io.getLocalizedMessage());
} catch (IllegalStateException ie) {
Log.v("Exception","IllegalStateException:" + ie.getLocalizedMessage());
}
}
I used the skip() method, as below, to skip the offset which is recorded when pause is triggered. Works fine sofar.
public void play() {
try {
dis.skip(offset); //skip "offset * bufferSize" in the **dis** data input stream
while (((i = dis.read(music_chunk, 0 , 0)) > -1) && !isPaused) {
i = dis.read(music_chunk, 0, bufferSize);
track.write(music_chunk, 0, i); // track is the AudioTrack
position += bufferSize;
}
track.stop();
}
public void pause() {
track.pause();
offset = position ;
isPaused = true;
}
Please adjust the above code to your needs before running.
Thanks
Related
I had this error on my VoiSip Application
E/AudioRecord: AudioFlinger could not create record track, status: -1
E/AudioGroup: cannot initialize audio device
This error occurs after I'm trying to make call to another sip address
Here have 2 java class(WalkieTalkieActivity.java & IncomingCallReceiver.java)
WalkieTalkieActivity.java
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
public IncomingCallReceiver callReceiver;
public SipManager mSipManager = null;
public SipProfile mSipProfile = null;
public SipAudioCall call = null;
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_walkie_talkie);
ToggleButton pushToTalkButton = (ToggleButton) findViewById(R.id.pushToTalk);
pushToTalkButton.setOnTouchListener(this);
IntentFilter filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);
if (mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}
tv = (TextView)findViewById(R.id.textView);
}
#Override
public void onStart() {
super.onStart();
// When we get back from the preference setting Activity, assume
// settings have changed, and re-login with new auth info.
initializeManager();
}
#Override
public void onDestroy() {
super.onDestroy();
if (call != null) {
call.close();
}
closeLocalProfile();
if (callReceiver != null) {
this.unregisterReceiver(callReceiver);
}
}
public void closeLocalProfile() {
if (mSipManager == null) {
return;
}
try {
if (mSipProfile != null) {
mSipManager.close(mSipProfile.getUriString());
}
} catch (Exception ee) {
Log.d("onDestroy", "Failed to close local profile.", ee);
}
}
public void initializeManager() {
if(mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}
initializeLocalProfile();
}
private void initializeLocalProfile() {
String domain = "mydomain";
String username = "myusername";
String password = "mypassword";
try {
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
mSipProfile = builder.build();
if (mSipProfile == null){
Log.e("error cukimai", "null");
}else{
Log.e("error cukimai", "not null");
}
Intent i = new Intent();
i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
mSipManager.open(mSipProfile, pi, null);
mSipManager.setRegistrationListener(mSipProfile.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
Log.e("process","Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
Log.e("process","ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
Log.e("process","Registration failed. Please check settings.");
}
});
Log.e("process","stop");
} catch (SipException e) {
e.printStackTrace();
Log.e("error cukimai", "cuk cuk");
} catch (ParseException e) {
e.printStackTrace();
Log.e("error cukimai", "cuk");
}
}
public void updateStatus(final String st){
this.runOnUiThread(new Runnable() {
public void run() {
tv.setText(st);
}
});
}
public void updateStatus(SipAudioCall call) {
String useName = call.getPeerProfile().getDisplayName();
if(useName == null) {
useName = call.getPeerProfile().getUserName();
}
updateStatus(useName + "#" + call.getPeerProfile().getSipDomain());
}
public void callAct(View view) {
Toast.makeText(this, "about to make call", Toast.LENGTH_LONG).show();
makeCall();
}
public void makeCall(){
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client's interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don't
// forget to set up a listener to set things up once the call is established.
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};
call = mSipManager.makeAudioCall(mSipProfile.getUriString(), "sip:destination#domain", listener, 30);
Log.e("make call", "true");
start();
}catch (Exception e){
Log.i("error", "Error when trying to close manager.", e);
if (mSipProfile != null) {
try {
mSipManager.close(mSipProfile.getUriString());
} catch (Exception ee) {
Log.i("error", "Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
#Override
public boolean onTouch(View view, MotionEvent event) {
if (call == null) {
return false;
} else if (event.getAction() == MotionEvent.ACTION_DOWN && call != null && call.isMuted()) {
call.toggleMute();
} else if (event.getAction() == MotionEvent.ACTION_UP && !call.isMuted()) {
call.toggleMute();
}
return false;
}
final MediaRecorder recorder = new MediaRecorder();
final String path;
/**
* Creates a new audio recording at the given path (relative to root of SD card).
*/
public WalkieTalkieActivity(String path) {
this.path = sanitizePath(path);
}
private String sanitizePath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.contains(".")) {
path += ".3gp";
}
return Environment.getExternalStorageDirectory().getAbsolutePath() + path;
}
/**
* Starts a new recording.
*/
public void start() throws IOException {
String state = android.os.Environment.getExternalStorageState();
if(!state.equals(android.os.Environment.MEDIA_MOUNTED)) {
throw new IOException("SD Card is not mounted. It is " + state + ".");
}
// make sure the directory we plan to store the recording in exists
File directory = new File(path).getParentFile();
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Path to file could not be created.");
}
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(path);
recorder.prepare();
recorder.start();
}
/**
* Stops a recording that has been previously started.
*/
public void stop() throws IOException {
recorder.stop();
recorder.release();
}
}
IncomingCallReceiver.java
public class IncomingCallReceiver extends BroadcastReceiver {
/**
* Processes the incoming call, answers it, and hands it over to the
* WalkieTalkieActivity.
* #param context The context under which the receiver is running.
* #param intent The intent being received.
*/
#Override
public void onReceive(Context context, Intent intent) {
SipAudioCall incomingCall = null;
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onRinging(SipAudioCall call, SipProfile caller) {
try {
call.answerCall(30);
} catch (Exception e) {
e.printStackTrace();
}
}
};
WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context;
incomingCall = wtActivity.mSipManager.takeAudioCall(intent, listener);
incomingCall.answerCall(30);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
if(incomingCall.isMuted()) {
incomingCall.toggleMute();
}
wtActivity.call = incomingCall;
wtActivity.updateStatus(incomingCall);
} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
}
}
}
}
I'm really new on Sip and Voip Implementing in Android Studio. I got this code from google source code.
I believe this error occurs because of the use of hardware (audio). However I have been searching on google for almost 1 week and not giving results. Can someone help me?
I had same problem but when i changed targetSdkVersion to 12 in build.gradel its fixed.
and this answer helped me to fixed problem .
You must choose the BufferSize when you want to record or call in app. For example:
int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
if (bufferSize > 0 && bufferSize <= 256){
bufferSize = 256;
}else if (bufferSize > 256 && bufferSize <= 512){
bufferSize = 512;
}else if (bufferSize > 512 && bufferSize <= 1024){
bufferSize = 1024;
}else if (bufferSize > 1024 && bufferSize <= 2048){
bufferSize = 2048;
}else if (bufferSize > 2048 && bufferSize <= 4096){
bufferSize = 4096;
}else if (bufferSize > 4096 && bufferSize <= 8192){
bufferSize = 8192;
}else if (bufferSize > 8192 && bufferSize <= 16384){
bufferSize = 16384;
}else{
bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
}
Hi I am stuck while i was trying to control 8x8 led matrix by cascading two 74hc595 shift registers. I had build the circuit and the program, which I am including here. It's actually giving me the right output. But the major problem is visible flickering. Can somebody guide me what can i do to remove the flickering?
public class MainActivity extends Activity {
private static final String SR_SRCLK_PIN = "BCM27"; //clock pins shcp
private static final String SR_RCLK_PIN = "BCM18"; //latch pin stcp
private static final String SR_SDI_PIN = "BCM17"; //data pin
private static final String TAG = "MAT21";
private Gpio mRCLK;
private Gpio mSRCLK;
private Gpio mSDI;
private int charSeq=0;
int data[]=
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //NULL
0x00,0x00,0x3C,0x42,0x42,0x3C,0x00,0x00, //0
0x00,0x00,0x00,0x44,0x7E,0x40,0x00,0x00, //1
0x00,0x00,0x44,0x62,0x52,0x4C,0x00,0x00, //2
0x00,0x00,0x78,0x14,0x12,0x14,0x78,0x00, //A
0x00,0x00,0x60,0x90,0x90,0xFE,0x00,0x00, //d
0x00,0x00,0x1C,0x2A,0x2A,0x2A,0x24,0x00, //e
0x00,0x00,0x7E,0x12,0x12,0x0C,0x00,0x00, //p
0x00,0x00,0x08,0x7E,0x88,0x40,0x00,0x00, //t
0x3C,0x42,0x95,0xB1,0xB1,0x95,0x42,0x3C, //:)
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PeripheralManagerService pms = new PeripheralManagerService();
try {
mRCLK = pms.openGpio(SR_RCLK_PIN);
mRCLK.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mSRCLK = pms.openGpio(SR_SRCLK_PIN);
mSRCLK.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mSDI = pms.openGpio(SR_SDI_PIN);
mSDI.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}
try {
thread.start();
while (true){
Thread.sleep(2000);
charSeq++;
if(charSeq==10){
charSeq=0;
}
}
} catch (Exception sd) {
}
}
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
for (int rowNum = 0; rowNum < 8; rowNum++) {
mRCLK.setValue(false);
shiftOut(data[(charSeq * 8) + rowNum],rowNum);
mRCLK.setValue(true);
}
}
}catch (Exception ex){
}
}
});
#Override
protected void onDestroy() {
super.onDestroy();
// Clean all resources
if (mSDI != null) {
try {
mSDI.setValue(false);
mSDI.close();
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}
}
if (mRCLK != null) {
try {
mRCLK.setValue(false);
mRCLK.close();
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}
}
if (mSRCLK != null) {
try {
mSRCLK.setValue(false);
mSRCLK.close();
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}
}
}
void shiftOut(int data, int rowNum) {
try {
for (int i = 7; i >= 0; i--) {
mSRCLK.setValue(false);
mSDI.setValue((((data >> i) & 1) == 0));
mSRCLK.setValue(true);
}
for (int i = 0; i <8; i++) {
mSRCLK.setValue(false);
mSDI.setValue(i==rowNum?true:false);
mSRCLK.setValue(true);
}
} catch (Exception sd) {
}
}
}
Schemetic Diagram
It's not entirely clear from your question what clock frequency you need to achieve to drive your matrix display properly, but regardless it's unlikely you will be able to get there bit-banging the GPIO in this fashion. The flickering you see is probably because the I/O is not toggling fast enough in your code.
I would recommend moving to an external hardware controller for your display (something like the MAX7219, for example) that you can control over a serial port like I2C or SPI.
using this url I wrote below code to encode onpreviewframe data to mp4 video and I used a thread to do this job well, but it seems that it doesn't work properly.
private void initCodec() {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/Vocalist");
if(!myDir.exists()) {
myDir.mkdirs();
}
try {
File file = new File (myDir, "myVideo.mp4");
if(file.exists()){
file.delete();
}
fos = new FileOutputStream(file, false);
} catch (FileNotFoundException e) {
e.printStackTrace();
}try {
mMediaCodec = MediaCodec.createEncoderByType("video/avc");
}
catch (Exception e){
}
MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc",
320,
240);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 500000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
mMediaCodec.configure(mediaFormat,
null,
null,
MediaCodec.CONFIGURE_FLAG_ENCODE);
mMediaCodec.start();
inputBuffers = mMediaCodec.getInputBuffers();
outputBuffers = mMediaCodec.getOutputBuffers();
}
private synchronized void encode(byte[] dataInput)
{
byte[] data = dataInput;
inputBuffers = mMediaCodec.getInputBuffers();// here changes
outputBuffers = mMediaCodec.getOutputBuffers();
int inputBufferIndex = mMediaCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(data);
mMediaCodec.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0);
} else {
return;
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 0);
Log.i("tag", "outputBufferIndex-->" + outputBufferIndex);
do {
if (outputBufferIndex >= 0) {
ByteBuffer outBuffer = outputBuffers[outputBufferIndex];
System.out.println("buffer info-->" + bufferInfo.offset + "--"
+ bufferInfo.size + "--" + bufferInfo.flags + "--"
+ bufferInfo.presentationTimeUs);
byte[] outData = new byte[bufferInfo.size];
outBuffer.get(outData);
try {
if (bufferInfo.offset != 0) {
fos.write(outData, bufferInfo.offset, outData.length
- bufferInfo.offset);
} else {
fos.write(outData, 0, outData.length);
}
fos.flush();
Log.i("camera", "out data -- > " + outData.length);
mMediaCodec.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo,
0);
} catch (IOException e) {
e.printStackTrace();
}
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
outputBuffers = mMediaCodec.getOutputBuffers();
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat format = mMediaCodec.getOutputFormat();
}
} while (outputBufferIndex >= 0);
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null) {
return;
}
try {
initCodec();
mCamera.setPreviewDisplay(mHolder);
mCamera.setPreviewCallback(new Camera.PreviewCallback() {
#Override
public void onPreviewFrame(final byte[] bytes, Camera camera) {
if (recording == true) {
if(mThread.isAlive())
encode(bytes);
}
}
});
} catch (Exception e) {
Log.d("TAG", "Error starting camera preview: " + e.getMessage());
}
}
}
public void newOpenCamera() {
if (mThread == null) {
mThread = new CameraHandlerThread();
}
synchronized (mThread) {
mThread.openCamera();
}
}
private static void oldOpenCamera() {
try {
c = Camera.open(1);
Camera.Parameters parameters = c.getParameters();
parameters.set("orientation", "portrait");
parameters.setJpegQuality(100);
parameters.setPreviewFormat(ImageFormat.NV21);
parameters.setPreviewSize(320, 240);
c.setParameters(parameters);
}
catch (RuntimeException e) {
Log.e("camera", "failed to open front camera");
}
}
public CameraHandlerThread mThread = null;
public static class CameraHandlerThread extends HandlerThread {
Handler mHandler = null;
CameraHandlerThread() {
super("CameraHandlerThread");
start();
mHandler = new Handler(getLooper());
}
synchronized void notifyCameraOpened() {
notify();
}
public void openCamera() {
mHandler.post(new Runnable() {
#Override
public void run() {
oldOpenCamera();
notifyCameraOpened();
}
});
}
}
I converted onpreviewframe data to a video but after first second video doesn't play smoothly. what should I do ?
First, you're not forwarding the timing information with the frames:
mMediaCodec.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0)
So your BufferInfo.presentationTimeUs will always be zero when you dequeue the buffer.
Second, you don't appear to be using MediaMuxer, which means you're just writing raw the raw H.264 stream to a file. This is not ".mp4"; it doesn't include the timing information at all. Many video players don't even know what to do with plain H.264.
Wrapping the file as .mp4, with the frame timing from the camera, should yield better results.
Your code structure appears to be assuming that it can feed one frame of input and get one frame of output, which isn't always the case. You want to keep the input full, and drain the output as it becomes available.
You can find more information and some sample code on bigflake and in Grafika.
I have a problem in using of long touch and multi thread programming.
I have 2 button: up and down. Each of these buttons have OnTouchListener event habdler . When I touch down in each of them, a thread will run inside them in the while(HelperClass.Universal_IsTouch == true) and in every 1000 milisec run again until tuouch up raised and "HelperClass.Universal_IsTouch" make false in touch up and it exit from the while .
in the while loop a thrad run and call another class method for sending data via run another thread via socket programming . So then when up button (or down) touched down long time , data should be send to server until touched up raised.
Its working but after many sending up and down when I touch long up (or down) its sended data related to other routin instead main routin ?
this is my UP routin code :
//////////// up
btn_UP_var.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
IntruptedAllThread();
// TODO Auto-generated method s tub
if (arg1.getAction() == MotionEvent.ACTION_DOWN)
{
HelperClass.Universal_IsTouch = true;
} else if (arg1.getAction() == MotionEvent.ACTION_UP) {
HelperClass.Universal_IsTouch = false;
}
//Send a simple Move (once)
if (chkbx_AutoMove_var.isChecked()) {
Img_Stop_var.setImageResource(R.drawable.arrow_stop_play);
Is_UP_buttonTouched = 1;
HelperClass.Is_Stop_Button_Disable = false;
} else {
HelperClass.Is_Stop_Button_Disable = true;
thread_UP = new Thread(new Runnable() {
#Override
public void run() {
while (HelperClass.Universal_IsTouch == true) {
Cursor ListHoist = mDbHelper.GetallSelectedHoistData();
//mDbHelper.close();
for (ListHoist.moveToFirst(); !ListHoist.isAfterLast(); ListHoist.moveToNext()) {
String IP = ListHoist.getString(ListHoist.getColumnIndex("HoistIP"));
int PK_hoist = ListHoist.getInt(ListHoist.getColumnIndex("PK_hoist"));
HelperClass.SendDataToMICRO(mDbHelper, PK_hoist, IP, HelperClass.Selector_Move_Stop,
HelperClass.MoveDesition_Up, HelperClass.inutile, HelperClass.inutile,
HelperClass.inutile);
}
ListHoist.close();
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
IntruptedAllThread();
}
}
// thread_UP.interrupt();
IntruptedAllThread();
}
});
thread_UP.start();
}
return true;
}
});
and this is my Down Code :
//////////// Down
btn_Down_var.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
IntruptedAllThread();
if (arg1.getAction() == MotionEvent.ACTION_DOWN)
{
HelperClass.Universal_IsTouch = true;
//txt_MovementValue_var.setText("1");
} else if (arg1.getAction() == MotionEvent.ACTION_UP)
{
HelperClass.Universal_IsTouch = false;
//txt_MovementValue_var.setText("0");
}
//Send a simple Move (once)
if (chkbx_AutoMove_var.isChecked()) {
Img_Stop_var.setImageResource(R.drawable.arrow_stop_play);
Is_UP_buttonTouched = 0;
HelperClass.Is_Stop_Button_Disable = false;
} else {
HelperClass.Is_Stop_Button_Disable = true;
thread_Down = new Thread(new Runnable() {
#Override
public void run() {
while (HelperClass.Universal_IsTouch == true) {
Cursor ListHoist = mDbHelper.GetallSelectedHoistData();
for (ListHoist.moveToFirst(); !ListHoist.isAfterLast(); ListHoist.moveToNext()) {
String IP = ListHoist.getString(ListHoist.getColumnIndex("HoistIP"));
int PK_hoist = ListHoist.getInt(ListHoist.getColumnIndex("PK_hoist"));
HelperClass.SendDataToMICRO(mDbHelper, PK_hoist, IP, HelperClass.Selector_Move_Stop,
HelperClass.MoveDesition_Down, HelperClass.inutile, HelperClass.inutile,
HelperClass.inutile);
}
ListHoist.close();
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
IntruptedAllThread();
}
}
//thread_Down.interrupt();
IntruptedAllThread();
}
});
thread_Down.start();
}
return true;
}
});
this is IntruptedAllThread()
public void IntruptedAllThread() {
if (thread_UP != null) {
thread_UP.interrupt();
thread_UP = null;
}
if (thread_Down != null) {
thread_Down.interrupt();
thread_Down = null;
}
}
and this is my thread to send data socket :
//This get each hoist data and change it to
//Int array to send to micro
public static void SendDataToMICRO(dbAdapter mDbHelper, int HoistID, final String Server_IP, int firstByte_KindType, int secoundByte_KindofMove,
int ValueOfMove, int valueOfsetting, int MaxOrMinValue) {
// mDbHelper = new dbAdapter(G.context);
// mDbHelper.createDatabase();
// mDbHelper.open();
Server_Port = mDbHelper.GetPortNumber();
//mDbHelper.close();
final String Concatinate_values = firstByte_KindType + Spliter + secoundByte_KindofMove +
Spliter + ValueOfMove + Spliter + valueOfsetting + Spliter + MaxOrMinValue;
//Sent Routin
////‌Connect To server
Thread thread = null;
thread = new Thread(new Runnable() {
#Override
public void run() {
DataOutputStream outputStream = null;
BufferedReader inputStream = null;
Socket socket;
socket = new Socket();
try {
socket.connect(new InetSocketAddress(Server_IP, Server_Port), 10);
}
catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
Thread.currentThread().interrupt();
}
////Make Read Line
try {
outputStream = new DataOutputStream(socket.getOutputStream());
inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
catch (IOException e1) {
//Finished Socket
ShutDown(socket);
}
if (outputStream == null) {
//
ShutDown(socket);
Thread.currentThread().interrupt();
return;
}
//Write Message
try {
String message = Concatinate_values + "\n";
outputStream.write(message.getBytes());
outputStream.flush();
ShutDown(socket);
Thread.currentThread().interrupt();
return;
}
catch (IOException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
try {
if (socket != null) {
socket.close();
}
}
catch (IOException e) {
e.printStackTrace();
ShutDown(socket);
Thread.currentThread().interrupt();
return;
}
Thread.currentThread().interrupt();
}
});
thread.start();
}
result
My application starts a thread A to save some data. In this thread I call the function startRecording(audioFile.getAbsolutePath());
But I get the following error:
start called in an invalid state: 16; at android.media.MediaRecorder.start(Native Method)
This error does not occur everytime, but sometimes I get this error report from my application.
Below, there's my code.
public void startRecording(String outputPath) {
if (recorder == null) {
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
recorder.setAudioSamplingRate(RECORDER_SAMPLERATE_22050);
recorder.setOutputFile(outputPath);
try {
recorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
recorder.start();
SampleRecordThread thread = new SampleRecordThread(outputPath);
thread.start();
}
private class SampleRecordThread extends Thread {
private volatile boolean running = true;
public void exit() {
running = false;
}
#Override
public void run() {
while (running) {
try {
Thread.sleep(10 * 1000);//to record 10 seconds sound
} catch (InterruptedException e) {
e.printStackTrace();
}
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
// upload the data to cloud
if (isWifiActive && isInstallationSaved) {
.....
record.saveInBackground();
}
break;
}
}
I think you try recording while previous recorder not stopped and released
You can use my class
public class AudioRecordManager {
public interface OnAudioRecordCallback {
void onComplete(String path);
void onFailed(int code);
}
private OnAudioRecordCallback onAudioRecordCallback;
public void setOnAudioRecordCallback(OnAudioRecordCallback onAudioRecordCallback) {
this.onAudioRecordCallback = onAudioRecordCallback;
}
private MediaRecorder myRecorder;
private String outputFile;
private AudioRecordThread audioRecordThread;
public AudioRecordManager() {
audioRecordThread = new AudioRecordThread();
}
private AudioRecordThread audioRecordThread;
public void startRecord() {
if(audioRecordThread == null || !audioRecordThread.isRunning()){
new Thread(audioRecordThread).start();
}
}
public void stopRecord() {
if(audioRecordThread!=null && audioRecordThread.isRunning()) {
audioRecordThread.stopRecording();
}
}
class AudioRecordThread implements Runnable {
private boolean isRunning;
private boolean isStop;
private long startTime;
private void startRecord() {
isRunning = true;
isStop = false;
File folder = new File(Content.AUDIO_DIR);
if (!folder.exists()) {
boolean b = folder.mkdirs();
}
startTime = System.currentTimeMillis();
outputFile = folder.getPath() + "/rec_" + startTime + ".mp3";
myRecorder = new MediaRecorder();
myRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
myRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
myRecorder.setOutputFile(outputFile);
try {
myRecorder.prepare();
myRecorder.start();
startTime = System.currentTimeMillis();
} catch (Exception e) {
e.printStackTrace();
}
}
private void stopRecord() {
final long stopTime = System.currentTimeMillis();
try {
if(System.currentTimeMillis() - startTime < 500){
try{
Thread.sleep(500);
}catch (Exception e){
e.printStackTrace();
}
}
myRecorder.stop();
myRecorder.release();
myRecorder = null;
} catch (Exception e) {
myRecorder = null;
e.printStackTrace();
}
if (stopTime - startTime > 1000) {
if (onAudioRecordCallback != null) {
onAudioRecordCallback.onComplete(outputFile);
}
} else {
File current = new File(outputFile);
current.delete();
if (onAudioRecordCallback != null) {
onAudioRecordCallback.onFailed(2);
}
}
isRunning = false;
}
#Override
public void run() {
startRecord();
while (!isStop) {
try {
Thread.sleep(30);
} catch (Exception e) {
e.printStackTrace();
}
}
stopRecord();
}
public void stopRecording() {
isStop = true;
}
public boolean isRunning() {
return isRunning;
}
}
}