This question was asked several times but none of the solutions are working for me. I am on kitkat(4.4.4)/Nexus5. Below are solutions I tried
1)Based on How to detect incoming calls, in an Android device? solution, I tried to retrieve the number from "extras". But intent.getExtras.getString always returns null
2)Based on Get phone number of present incoming and outgoing call solution, I tried to read from the log, but "cur.getString(0)", always returns null
I am NOT using TelephonyManager any where in my code (though few in above links seem to be using telephonymanager). I am using BroadcastReceiver. My code is below. I ended up trying above 2 solutions, because I am getting null value(callingNumber) in my callback below.
public class MyPhoneStateListener extends PhoneStateListener {
//blah blah
public void onCallStateChanged(int state, String callingNumber)
{
//callingNumber is always null, unfortunately
}
}
For me this work, try and tell me
import org.jivesoftware.smackx.xdata.Form;
import org.jivesoftware.smackx.xdata.packet.DataForm;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
public class MyIncomingCallListenerService extends BroadcastReceiver {
private StringBuffer incomingCall = new StringBuffer();
#Override
public void onReceive(Context context, Intent intent) {
try {
TelephonyManager tmgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
MyPhoneStateListener PhoneListener = new MyPhoneStateListener();
tmgr.listen(PhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e) {
e.printStackTrace();
}
}
private class MyPhoneStateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
Log.d("MyPhoneListener",state+" incoming no:"+incomingNumber);
}
}
}
}
Related
I have built full voice recorder application.
I would like to start recording when a voice call starts on the phone, how can I detect the Calls state? tried some code and it didn't work for me.
I just need to know hot to start recording when a voice call starts (incoming and outgoing).
Here is an example of what you need.
Declare receiver in AndroidManifest
<receiver android:name=".IncomingCall">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
Give read phone state permission in AndroidManifest
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Create a class IncomingCall with extends BroadcastReceiver class
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
/**
* Created by matheszabi on Aug/20/2017 0020.
*/
public class IncomingCall extends BroadcastReceiver {
private Context context;
public void onReceive(Context context, Intent intent) {
this.context = context;
try {
// TELEPHONY MANAGER class object to register one listner
TelephonyManager tmgr = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
//Create Listner
MyPhoneStateListener PhoneListener = new MyPhoneStateListener();
// Register listener for LISTEN_CALL_STATE
tmgr.listen(PhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e) {
Log.e("Phone Receive Error", " " + e);
}
}
private class MyPhoneStateListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
Log.d("MyPhoneListener",state+" incoming no:"+incomingNumber);
if (state == 1) {
String msg = "New Phone Call Event. Incomming Number : "+incomingNumber;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, msg, duration);
toast.show();
}
}
}
}
Above Android 6.0 you need to handle a bit different the permissions:
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final int MY_REQUEST_CODE = 1234;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE},
MY_REQUEST_CODE);
}
}
public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == MY_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Now user should be able to use camera
Toast.makeText(this, "I have access", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "I DON'T have access", Toast.LENGTH_SHORT).show();
}
}
}
}
You must allow the permissions at the first time run:
Here is the screenshot of the working code:
I found how to do so:
package com.example.tsuryohananov.mycallrecorder;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
/**
* Created by tsuryohananov on 20/08/2017.
*/
public class MyPhoneReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
String state = extras.getString(TelephonyManager.EXTRA_STATE);
Log.d("MY_DEBUG_TAG", state);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
String phoneNumber = extras.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.d("MY_DEBUG_TAG", phoneNumber);
// here i need to save the number for the listview.
}
if ((state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))){
String phoneNumber = extras.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Toast.makeText(context,"Answered" + phoneNumber, Toast.LENGTH_SHORT).show();
MainActivity.recordStart();
}
if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
Toast.makeText(context,"Idle State", Toast.LENGTH_SHORT).show();
MainActivity.stopRecord();
}
}
}
}
I am originating a call from Android Studio. The code is as follows:
I want to get the state of the call at any point. The link: https://developer.android.com/reference/android/telecom/Call.html
shows the state of the call can be obtained by using the Class call.. SO if I use Call.getState() I should be able to get the current state. But I get the compilation error:
Error:(28, 20) error: Call() is not public in Call; cannot be accessed from outside package. There are several call states defined in the enum: Dialing, Ringing, Connected, DIsconnected, Holding, etc.
When I run the code, it does make the call as I can see the screen of emulator making the call.
The developer guide does not provide any examples of using these classes.
Thank you for your help.
package com.example.ramesh.makeacall;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.telecom.Call;
import android.telephony.*;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Call call;
call = new Call();
call();
}
private void call() {
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:5555551212"));
System.out.println("====before startActivity====");
startActivity(callIntent);
} catch (ActivityNotFoundException e) {
Log.e("helloAndroid","Call failed",e);
}
}
}
Try to use like this(Haven't tried it though) -
Call.Callback callback = new Call.Callback() {
#Override
public void onStateChanged(Call call, int state) {
super.onStateChanged(call, state);
if(state == Call.STATE_RINGING){
//you code goes here
}
}
};
public class MyPhoneStateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
handleRinging(incomingNumber);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
handleOffHook();
break;
case TelephonyManager.CALL_STATE_IDLE:
handleIdle();
break;
}
super.onCallStateChanged(state, incomingNumber);
}
}
and register statelistener :
telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(myPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
My Note :as I have already clarified in my initial post, I don't think it's a duplicate,
I already tried these method and it doesn't work for me,
The code below seems only work for 2.2, it requires MODIFY_PHONE_STATE which is not permitted after Android 2.2****
This is not duplicated questions since i have already looked many other post here and it doesn't work for me
I follow the solution from the link below:
block phone call
TelephonyManager tm = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
Class<?> c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
But the code give me exception when run on real device(which is Android 4.2)
java.lang.NoSuchMethodException: getITelephony
So, does it still possible use this solution on Android 4.2, if not,does there exist other solutions i can try?
Thanks a lot in advance
Create a file named ITelephony.aidl it should contain these data:
package com.android.internal.telephony;
interface ITelephony
{
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
Create these folders under src
android > internal > telephony
Then Place the ITelephony.adl under telephony folder.
Copy this DeviceStateListener class and place it under any package on your project.
import android.content.Context;
import android.os.RemoteException;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import java.lang.reflect.Method;
public class DeviceStateListener extends PhoneStateListener {
private ITelephony telephonyService;
private Context context;
public DeviceStateListener(Context context) {
this.context = context;
initializeTelephonyService();
}
private void initializeTelephonyService() {
try {
TelephonyManager telephonyManager = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
Class clase = Class.forName(telephonyManager.getClass().getName());
try{
Method method = clase.getDeclaredMethod("getITelephony");
}catch (NoSuchMethodException e){
e.printStackTrace();
}
method.setAccessible(true);
telephonyService = (ITelephony) method.invoke(telephonyManager);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onCallStateChanged(int state, final String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
boolean isNumberIsBlocked=false;
// You can check here if incomingNumber string is under your blacklisted numbers
if (isNumberIsBlocked) {
try {
// This is the main code that block the incoming call.
telephonyService.endCall();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
// You can run anything here lets say a notice to the user if a call is blocked
}
});
t.start();
} catch (RemoteException e) {
e.printStackTrace();
}
}
break;
}
}
}
Here is another important class "ServiceReceiver" place it also under any package of your project and resolve all possible imports.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class ServiceReciever extends BroadcastReceiver
{
private static TelephonyManager telephony;
private static DeviceStateListener phoneListener;
private static boolean firstTime=true;
public ServiceReciever(Context context)
{
telephony=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
phoneListener=new DeviceStateListener(context);
}
#Override
public void onReceive(Context context, Intent intent)
{
if(firstTime)
{
telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
firstTime = false;
}
}
// You can use this in the future to stop the call blocker feature.
public void stopListening() {
telephony.listen(phoneListener, PhoneStateListener.LISTEN_NONE);
firstTime=true;
}
}
Copy this CallBlockerService class also and place it under any package of your project. It is an unkillable service that invokes the ServiceReceiver class.
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import com.katadigital.phone.callsmsblocker.callListener.ServiceReciever;
public class CallBlockerService extends Service {
public static final int notification_id = 111;
// ---------------------------------------
// Listening Services
// ---------------------------------------
private static ServiceReciever service;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
service = new ServiceReciever(getApplicationContext());
registerReceiver(service, new IntentFilter(
"android.intent.action.PHONE_STATE"));
System.out.println("Call blocker is running now");
}
#Override
public void onDestroy() {
service.stopListening();
unregisterReceiver(service);
service = null;
cancelStatusBarNotification();
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public void cancelStatusBarNotification() {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(notification_id);
}
}
Place this AfterBootReceiver class beside our CallBlockerService. Its job is to restart the blocker service when the phone starts from shutdown.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class AfterBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Intent serviceLauncher = new Intent(context, CallBlockerService.class);
context.startService(serviceLauncher);
}
}
Lastly place this on your AndroidManifest under tag.
<receiver android:name="com.callblocker.services.AfterBootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:name="com.callblocker.services.CallBlockerService" >
</service>
Replace "com.callblocker.services" with the folder location of the CallBlockerService and your AfterBootReceiver
I have tested this code until Android 4.4 KitKat. I hope you can follow the steps and it helps you with your problem.
i have this very basic code that should work as a call application.
everything is hardcoded.
i don't find usefull tutorials according to this application i need / want to create.
my question is large ! Can anyone pls help me creating a CallApplication
requirement is simple i think
need to be able to dail a number
this is the code i have at the moment, as said it is very basic, but i'm stuck ^^
any help is much appreciated!
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
final Context context = this;
private Button btn;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.button);
PhoneCallListener phoneCallListener = new PhoneCallListener();
TelephonyManager telManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
telManager.listen(phoneCallListener, PhoneStateListener.LISTEN_CALL_STATE);
// add button listener
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
Intent phoneCallIntent = new Intent(Intent.ACTION_CALL);
phoneCallIntent.setData(Uri.parse("tel:123456"));
startActivity(phoneCallIntent);
}
});
}
// monitor phone call states
private class PhoneCallListener extends PhoneStateListener {
String TAG = "LOGGING PHONE CALL";
private boolean phoneCalling = false;
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (TelephonyManager.CALL_STATE_RINGING == state) {
// phone ringing
Log.i(TAG, "RINGING, number: " + incomingNumber);
}
if (TelephonyManager.CALL_STATE_OFFHOOK == state) {
// active
Log.i(TAG, "OFFHOOK");
phoneCalling = true;
}
// When the call ends launch the main activity again
if (TelephonyManager.CALL_STATE_IDLE == state) {
Log.i(TAG, "IDLE");
if (phoneCalling) {
Log.i(TAG, "restart app");
// restart app
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(
getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
phoneCalling = false;
}
}
}
}
}
As per #SeeSharp comment.
I guess your requirement is to remove hardcoded contact.
Way 1:
Take contact as Input from User (Example in EditText , Design UI).
Way 2:
Use Getting a Result from an Activity to get contact from Contacts App.
startActivityForResult() Contacts Application to Pick a contact from android.provider.ContactsContract. More at : this and this.
Read ContactsContract.
Note : Please make your problem/Issue in question explanatory enough to be understood.
Hope this helps !!
When i try to detect incoming calls with PhoneStateListener, it executes multiple times.
This is my code. onCallStateChanged method is called multiple times.
public class CallHelper {
public String number;
private Context ctx;
private TelephonyManager tm;
private CallStateListener callStateListener;
private OutgoingReceiver outgoingReceiver;
SharedPreferences trackMeData;
public CallHelper(Context ctx) {
this.ctx = ctx;
number ="";
callStateListener = new CallStateListener();
outgoingReceiver = new OutgoingReceiver();
trackMeData = ctx.getSharedPreferences("LockedSIM", 0);
}
private class CallStateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
number = incomingNumber;
sendsmstoph(number);
System.out.println("Incomgin");
Toast.makeText(ctx, "Incoming: " + incomingNumber,Toast.LENGTH_LONG).show();
break;
}
}
}
Using BroadcastReceiver with functionality of PhoneStateListener
In above line: The problem is that every time when the onReceive() method is called a new TelphoneManager instance is created and registers as a listener to Phoone State .
Solution :
I made every variable of the CallReceiverBroadcast class static ! and it solved the problem !! to an extent but still the service is called twice every time it means that some how there is 2 instance of the class registered as a listener but i don't know why. Although i can work around it through some condition but it is causing unnecessary overhead and Anyone having a better solution will be highly Appreciated .
package com.example.netlogger.Receiver;
import java.util.Date;
import com.example.netlogger.util.LocalDatabase;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.telephony.TelephonyManager;
import android.util.Log;import android.widget.Toast;
public class CallActionsReceiver extends BroadcastReceiver {
static ThePhoneStateListener phoneStateListener;
#Override
public void onReceive(Context arg0, Intent arg1) {
TelephonyManager manager = (TelephonyManager) arg0
.getSystemService(arg0.TELEPHONY_SERVICE);
if (phoneStateListener == null) {
phoneStateListener = new ThePhoneStateListener(arg0);
manager.listen(phoneStateListener,
android.telephony.PhoneStateListener.LISTEN_CALL_STATE);
}
}
}