We are building android app using multi threading as its working on almost all device except MI and few other devices that not supported Multi threading.
Try to call recording service in background using new threads. for that we create stopRecording() function that will call in new threads and its work in all device well but only few device like MI not working as we assumed there are not multi thread support in these devices ?
we are using below code
if(TelephonyManager.EXTRA_STATE_IDLE.equals(state)&&recording==true)
{
//Toast.makeText(getApplicationContext(), state, Toast.LENGTH_LONG).show();
//Toast.makeText(arg0, "STOP Called :"+recording, Toast.LENGTH_LONG).show();
stopRecording();
}
public void stopRecording()
{
if(recording==true)
{
try
{
te = getCurrentTS();
recorder.stop();
recorder.reset();
recorder.release();
recorder=null;
recording=false;
editor.putString("mdialerRecording", "false");editor.commit();
//broadcastIntent();
//Toast.makeText(getApplicationContext(), "Recorder_Relesed", Toast.LENGTH_LONG).show();
File oldfile = new File(fname);
byte[] fileData = new byte[(int) oldfile.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(oldfile));
dis.readFully(fileData);
dis.close();
oldfile.delete();
try
{
String s64mp3file=Base64.encodeToString(fileData,Base64.NO_WRAP);
String newKey=calledCRM+"_"+sysNumber+"_"+ts+"_"+te;
editor.putString(newKey, s64mp3file);
String mdialerKeys=settings.getString("mdialerKeys", "");
editor.putString("mdialerKeys", mdialerKeys+"|"+newKey);
editor.commit();
}
catch(Exception e)
{
//Toast.makeText(getApplicationContext(), "File_EX "+e.toString(), Toast.LENGTH_LONG).show();
}
calledCRM="";
if(calledNum.equals(sysNumber))deleteLogNumber(sysNumber);
calledNum="";
}
catch(Exception e)
{
//Toast.makeText(getApplicationContext(), "Rec_Stop_EX "+e.toString(), Toast.LENGTH_LONG).show();
}
}
}
Related
After recording an outgoing phone call, I am trying to play the recorded file - to make sure the call recording worked as expected (I am doing it using 'MediaPlayer'), but there is no sound.
So I tried to access the actual file on the phone (simply attached the phone to the computer and accessed it's files). When I played it the recording it was in the right length but again no sound.
What am I missing?
This is how I record the phone call:
MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
// recorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
File callAudioFile = null;
try {
File downloadsDir = context.getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
callAudioFile = File.createTempFile("deTuCelRecord", ".amr", downloadsDir);
} catch (IOException e) {
e.printStackTrace();
}
assert callAudioFile != null;
audioFilePath = callAudioFile.getAbsolutePath();
recorder.setOutputFile(audioFilePath);
try {
recorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
#Override
public void onError(MediaRecorder mr, int what, int extra) {
Log.e("MediaRecorder", "MediaRecorder error " + what + " " + extra);
}
});
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
recorder.start();
This is the code which ends the call recording:
recorder.stop();
recorder.release();
This is how I play the audio file:
MediaPlayer mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(audioFilePath);
mPlayer.prepare();
Toast.makeText(getApplicationContext(), "PLAYING AUDIO", Toast.LENGTH_LONG).show();
mPlayer.start();
Log.d("PLAY_AUDIO", "Started playing audio");
} catch (IOException e) {
Log.e("PLAY_AUDIO", "Failed to play audio");
}
Please check this Accessibilty Service in your testing phone.
If you are trying to record call on Android Q.
Please refer this link
You can try
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL); It need Manifest.permission.CAPTURE_AUDIO_OUTPUT permission.
Please check AudioSource Source documentation for difference between VOICE_CALL and VOICE_COMMUNICATION
The issue was the android version - from android 10 it didn't allow me to record the call but on android 9 it did.
In android studio I am able to create a mediaRecorder instance and record audio, I can then create an instance of a mediaRecorder with a different audio source and record audio. The problem is that I cannot have two mediaRecorders at one time (or so I think).
In addition to mediaRecorder, I have looked into using two different AudioRecord objects but it appears someone here tried that about a month ago and it does not work either. I have looked into the mediaMuxer which may be the key to this, but I am new to the concept of multiplexing and do not know how to implement something of this kind.
// not to professional standards
btnRecord.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(checkPermissionFromDevice()) {
pathsave = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/"
+ UUID.randomUUID().toString() +
"_audio_record.3gp";
setupMediaRecorder();
try {
mediaRecorder.prepare();
mediaRecorder.start();
} catch (IOException e) {
e.printStackTrace();
}
btnPlay.setEnabled(false);
btnStop.setEnabled(false);
btnStopRecord.setEnabled(true);
Toast.makeText(MainActivity.this, "Recording...",
Toast.LENGTH_SHORT).show();
}
else{
requestPermission();
}
}
});
//------------------------------------------------------------------------
btnRecord2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(checkPermissionFromDevice()) {
pathsave2 = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/"
+ UUID.randomUUID().toString() +
"_audio_record.3gp";
setupMediaRecorder2();
try {
mediaRecorder2.prepare();
mediaRecorder2.start();
} catch (IOException e) {
e.printStackTrace();
}
btnPlay2.setEnabled(false);
btnStop2.setEnabled(false);
btnStopRecord2.setEnabled(true);
Toast.makeText(MainActivity.this, "Recording...",
Toast.LENGTH_SHORT).show();
}
else{
requestPermission();
}
}
});
//-----------------------------------------------------------------------
private void setupMediaRecorder() {
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
mediaRecorder.setOutputFile(pathsave);
}
//------------------------------------------------------------------------
private void setupMediaRecorder2() {
mediaRecorder2 = new MediaRecorder();
mediaRecorder2.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder2.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder2.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
mediaRecorder2.setOutputFile(pathsave2);
}
I can record, stop recording and playback both media recorders separately. When I try to record both at the same time, the app crashes. Any help would be greatly appreciated.
I am developing an Android app that is going to communicate with target miroprocessor(ARM processor) board through a bluetooth device(RN4020).
Since the pair PIN is random for each bluetooth module, I just want the app source code to connect the app with that RN4020 module (without pairing manually since I don't know the pair PIN).
Also, I just want to know the UUID for RN4020 module, I have tried to find the UUID through some Android app it shows more than ten UUIDs. I am confused to choose the appropriate UUID.
Here is my code:
private static String address = "00:1E:C0:19:DB:A6";
private static final UUID MY_UUID = UUID.fromString("00002A00-0000-1000-8000-00805F9B34FB");
connect.setOnClickListener(new View.OnClickListener()
{
public void onClick(View V)
{
Toast.makeText(getApplicationContext(), "Connecting to ... RN4020_D694", Toast.LENGTH_SHORT).show();
if (mBluetoothAdapter.isEnabled())
Connect();
}
});
public void Connect() {
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
Toast.makeText(getApplicationContext(), "Connecting to ... " + device, Toast.LENGTH_SHORT).show();
mBluetoothAdapter.cancelDiscovery();
try {
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
btSocket.connect();
Toast.makeText(getApplicationContext(), "Connection made", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
try {
btSocket.close();
} catch (IOException e2) {
changingText.setText("Unable to end the connection");
}
Log.d(TAG, "Socket creation failed");
}
beginListenForData();
}
When I tried to press the connect button, my app got stuck and it's not responding.
To avoid pairing you need to go for an insecure UUID rfcomm.
Replace:
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
with
btSocket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
I have some mp3 files on a cloud service.The links are like that https://dns/mp3filename.mp3?dl=1. I can play the files streaming with Vlc media player and I can write the bytes in files in Java. But when I try to play the links in Android media player some times it plays some times I get error(1,-1004) that is media_error_io.
Streaming code:
mp.setDataSource(link);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.prepareAsync();
mp.setWakeMode(ctx, PowerManager.PARTIAL_WAKE_LOCK);
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
I have been looking for a library but I could not found one. I just came with the idea about download the file and play it while downloading, but the media player only reads the first bytes I give it to play and called setOnCompletionListener even if the file have been completely downloaded.
That code is in a thread and it's for download the file
try {
File cacheDir = new File(ctx.getCacheDir().getPath()+"/"+"mp3s");
cacheDir.mkdir();
File tempFile = File.createTempFile("mp3" + num, ".mp3", cacheDir);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(tempFile));
HttpURLConnection httpURLConnection = (HttpURLConnection) new URL(lien).openConnection();
httpURLConnection.setDoInput(true);
BufferedInputStream bufferedInputStream = new BufferedInputStream(httpURLConnection.getInputStream());
byte bytes[] = new byte[1048576];
int len = 0;
int nbre = 0;
int current = 0;
while ((len = bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,len);
bufferedOutputStream.flush();
nbre+= len;
current += len;
onLoadingListener.onLoading(current, httpURLConnection.getContentLength());
if(nbre >= 524288){
nbre = 0;
onReadyListener.onReady(tempFile);
}
}
bufferedOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
onReadyListener.onReady(tempFile); is callback to start the media player like that.
playerMediaDownloader.setOnReadyListener(new PlayerMediaDownloader.OnReadyListener() {
#Override
public void onReady(final File file) {
path = file.getPath();
try {
if(!playing) {
Log.d(getClass().getSimpleName(), "li ready");
mp.setDataSource(file.getPath());
mp.prepare();
mp.start();
Log.d(Player.this.getClass().getSimpleName(), "pos:"+mp.getCurrentPosition());
playing = true;
for (OnTimeChanged l : onTimeChangeds) {
l.onTimeChanged(mp.getCurrentPosition(), mp.getDuration());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
The media player finished to play the file when it reach the 524288 bytes even if the file has been completely downloaded.
I came with another solution that is set the file file again and play it and it worked but, the sound cut a bit and it is not pretty like that.
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
int currentPosition = mp.getCurrentPosition();
mp.reset();
try {
Player.this.mp.setDataSource(path);
mp.prepare();
mp.seekTo(currentPosition);
mp.start();
} catch (Exception e) {
e.printStackTrace();
}
Log.d(getClass().getSimpleName(), "fini jwe:"+mp.getCurrentPosition());
}
});
Do you have a better solution to help me make it works fine please, like playing the file asynchronously?
The requirements: ensure that the PDF document is deleted from the device after the user has left the PDF viewing screen
The problem: on certain devices (Samsung 4.4.2 and Samsung 4.1.2 for sure, but not Asus 4.2.1) only the first time that the PDF is requested after restarting the application an error message is displayed stating "This document cannot be opened". Thereafter the PDF will load normally. I'm thinking this is a timing issue due to processes that need to be started the first time, but are running after the first attempted load.
The code: note that createFile() is called first, then startActivityForIntentResult()
private File file;
private ArrayList<Uri> uriList = new ArrayList<Uri>();
private void createFile() {
int fileNameLength = pdfFileName[0].length();
String fileName = pdfFileName[0].substring(0, fileNameLength - 4) + DateTime.now();
String fileExtension = pdfFileName[0].substring(fileNameLength - 4, fileNameLength);
byte[] content = Base64.decodeBase64(pdfData[0].getBytes());
BufferedOutputStream outputStream = null;
try {
File path = new File(getExternalFilesDir(null).getAbsolutePath(), "temp");
if (!path.exists()) {
path.mkdirs();
}
file = new File(path, fileName + fileExtension);
outputStream = new BufferedOutputStream(new FileOutputStream(file));
outputStream.write(content);
file.deleteOnExit();
uriList.add(Uri.fromFile(file));
}
catch (FileNotFoundException ex) {
ex.printStackTrace();
}
catch (IOException ex) {
ex.printStackTrace();
}
finally {
try {
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
private static int REQUEST_CODE = 1;
private Intent intent;
private void startActivityForIntentResult() {
if (file.exists()) {
Uri targetUri = uriList.get(0);
intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(targetUri, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
try {
startActivityForResult(intent, REQUEST_CODE);
}
catch (ActivityNotFoundException e) {
toastTitle = "Error Displaying PDF";
toastMessage = "Please make sure you have an application for viewing PDFs installed on your device and try again.";
toast = new GenericCustomToast();
toast.show(toastTitle, toastMessage, QueryForPDF.this);
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode == RESULT_CANCELED && requestCode == REQUEST_CODE) {
if(!file.delete()) {
file.delete();
}
}
searchAgain();
}
#Override
public void onBackPressed() {
super.onBackPressed();
if(!file.delete()) {
file.delete();
}
searchAgain();
}
#Override
public void onStop() {
super.onStop();
if(!file.delete()) {
file.delete();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if(!file.delete()) {
file.delete();
}
}
EDIT: I have also tried implementing a callback to be absolutely certain that createFile() has finished it's work. I even tried adding delays (of different time increments) as well as adding (the completely unnecessary) flags for Intent.FLAG_GRANT_READ_URI_PERMISSION, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, and Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION.
I still don't know why this works, but here's the solution in case anyone else runs into this issue:
It's the directory where the file is created. For some reason on the two Samsung devices there was something different in how the files were either accessed or created versus the Asus device. So File path = new File(getExternalFilesDir(null).getAbsolutePath(), "temp"); becomes File path = new File(getExternalCacheDir().getAbsolutePath()); and the problem goes away.