Reputation: 1
This is my Receiver Class where i'm getting phone state of both incoming and outgoing calls
public class MyBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "MyBroadcastReceiver";
//The receiver will be recreated whenever android feels like it. We need a static variable to remember data between instantiations
private String phoneIncomingNumber = "";
private String PhoneState = "";
private String Message = "";
private MediaRecorder recorder;
Context context;
//Call Recording varibales
private static final String AUDIO_RECORDER_FILE_EXT_3GP = ".3gp";
private static final String AUDIO_RECORDER_FILE_EXT_MP4 = ".mp3";
private static final String AUDIO_RECORDER_FOLDER = "Recordings";
Uri audiouri;
ParcelFileDescriptor file;
AudioManager audioManager;
private int currentFormat = 0;
private int output_formats[] = { MediaRecorder.OutputFormat.MPEG_4,
MediaRecorder.OutputFormat.THREE_GPP };
private String file_exts[] = { AUDIO_RECORDER_FILE_EXT_MP4,
AUDIO_RECORDER_FILE_EXT_3GP };
//The receiver will be recreated whenever android feels like it. We need a static variable to remember data between instantiations
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber; //because the passed incoming is only valid in ringing
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// Registering service
context.startService(new Intent(context, MyService.class));
// Getting Call Details
String stateStr = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
phoneIncomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.d("Call Status1", "Number1: " + phoneIncomingNumber + ":STATE : " + stateStr);
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = intent.getStringExtra("android.intent.extra.PHONE_NUMBER");
} else {
phoneIncomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
state = TelephonyManager.CALL_STATE_IDLE;
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
state = TelephonyManager.CALL_STATE_OFFHOOK;
startRecording(getRecordFileName(phoneIncomingNumber), context);
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(context, state, phoneIncomingNumber);
}
}
//Derived classes should override these to respond to specific events of interest
protected void onIncomingCallStarted(Context ctx, String number, Date start) {
Message = "Call from : \"+number+\" on DATE \"+start+\" started";
Log.d("Call Status", "INCOMING CALL STARTED");
}
protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
Message = "Call to : \"+number+\" on DATE \"+start+\" started";
Log.d("Call Status", "OUTGOING CALL STARTED to :" + number);
PhoneState = "OFFHOOK";
}
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
Log.d("Call Status", "INCOMING CALL ENDED");
Message = "Call from : \"+number+\" on DATE \"+start+\" ended";
stopRecording();
}
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
Message = "Call to : \"+number+\" on DATE \"+start+\" ended";
Log.d("Call Status", "OUTGOING CALL ENDED");
stopRecording();
}
protected void onMissedCall(Context ctx, String number, Date start) {
Message = "Missed call : \"+number+\" on DATE \"+start+\"";
Log.d("Call Status", "MISSED CALL");
}
//Deals with actual events
//Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
//Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
public void onCallStateChanged(Context context, int state, String number) {
Log.d("Call", "Number: " + number);
if (lastState == state) {
//No change, debounce extras
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
PhoneState = "RINGING";
onIncomingCallStarted(context, number, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
if (lastState != TelephonyManager.CALL_STATE_RINGING) {
isIncoming = false;
callStartTime = new Date();
PhoneState = "OFFHOOK";
onOutgoingCallStarted(context, phoneIncomingNumber, callStartTime);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
//Went to idle- this is the end of a call. What type depends on previous state(s)
if (lastState == TelephonyManager.CALL_STATE_RINGING) {
//Ring but no pickup- a miss
PhoneState = "IDLE";
onMissedCall(context, phoneIncomingNumber, callStartTime);
} else if (isIncoming) {
PhoneState = "INCOMING CALL ENDED";
onIncomingCallEnded(context, phoneIncomingNumber, callStartTime, new Date());
} else {
PhoneState = "OUTGOING CALL ENDED";
onOutgoingCallEnded(context, phoneIncomingNumber, callStartTime, new Date());
}
break;
}
lastState = state;
}
private MediaRecorder.OnErrorListener errorListener = new MediaRecorder.OnErrorListener() {
@Override
public void onError(MediaRecorder mr, int what, int extra) {
Toast.makeText(context,
"Error: " + what + ", " + extra, Toast.LENGTH_SHORT).show();
}
};
private MediaRecorder.OnInfoListener infoListener = new MediaRecorder.OnInfoListener() {
@Override
public void onInfo(MediaRecorder mr, int what, int extra) {
Toast.makeText(context,
"Warning: " + what + ", " + extra, Toast.LENGTH_SHORT)
.show();
}
};
// Recording Audio
private void startRecording(String fileName, Context ctx) {
Log.d("Call Status", "Inside");
ContentValues values = new ContentValues(4);
values.put(MediaStore.Audio.Media.TITLE, fileName);
values.put(MediaStore.Audio.Media.DATE_ADDED, (int) (System.currentTimeMillis() / 1000));
values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/mpeg");
values.put(MediaStore.Audio.Media.RELATIVE_PATH, "Music/Recordings/");
audiouri = ctx.getContentResolver().insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
Log.d("Call Status", "Call Status: "+audiouri);
try {
file = ctx.getContentResolver().openFileDescriptor(audiouri, "w");
} catch (Exception e) {
Log.d("Call Status", "File Error"+e);
}
audioManager = (AudioManager) ctx.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_IN_CALL);
// audioManager.setSpeakerphoneOn(true);
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
recorder.setOutputFormat(output_formats[currentFormat]);
//recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(file.getFileDescriptor());
recorder.setOnErrorListener(errorListener);
recorder.setOnInfoListener(infoListener);
try {
recorder.prepare();
recorder.start();
} catch (IllegalStateException e) {
Log.e("REDORDING :: ",e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Log.e("REDORDING :: ",e.getMessage());
e.printStackTrace();
}
}
private void stopRecording() {
// audioManager.setSpeakerphoneOn(false);
try{
if (null != recorder) {
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
}
}catch(Exception stopException){
Log.d("Exce",stopException+"");
}
}
private String getRecordFileName(String phoneNumber) {
// Generate a unique file name based on the phone number and the current time
String timeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
return phoneNumber + "_" + timeStamp + ".wav";
}
}
My Service Class to run receiver as a forground service
public class MyService extends Service {
private static final int SERVICE_NOTIFICATION_ID =2 ;
private static final String CHANNEL_ID = "PhoneStateModule";
public MyService() {
}
private Handler handler = new Handler();
private Runnable runnableCode = new Runnable() {
@Override
public void run() {
try{
handler.postDelayed(this, 2000);
}catch (Exception ex){
Log.d("Error",ex+"");
}
}
};
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "PhoneStateModule", importance);
channel.setDescription("CHANEL DESCRIPTION");
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.handler.post(this.runnableCode); // Starting the interval
// Turning into a foreground service
createNotificationChannel(); // Creating channel for API 26+
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT|PendingIntent.FLAG_MUTABLE);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Phone Recording Service")
.setContentText("Running…")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(contentIntent)
.setOngoing(true)
.build();
startForeground(SERVICE_NOTIFICATION_ID, notification);
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
}
Can anyone help me with the issue facing, I am using device with android 10 and am not getting the recordings, even if the recording is saved inside folder I'm not getting any audio.
Upvotes: 0
Views: 144