Backgroud
I am developing an app which makes calls like lollpop. When a call comes it should show a popup on the screen and the default calling screen should not be visible.
What I have done
I have build the broadcast receiver and currently I am able to show a popup every time a call come.
by using this code
public class PhoneCallReceive extends BroadcastReceiver {
Class<?> c;
public static ITelephony telephonyService = null;
TelephonyManager telephony;
Method m;
public static int flag = 0;
public static AudioManager audioManager;
#Override
public void onReceive(Context conk, Intent inter) {
final Context context = conk;
final Intent intent = inter;
Thread pageTimer = new Thread() {
public void run() {
try {
sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
try {
telephony = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
c = Class.forName(telephony.getClass().getName());
m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
telephonyService = (ITelephony) m.invoke(telephony);
audioManager = (AudioManager) context
.getSystemService(Context.AUDIO_SERVICE);
} catch (Exception e) {
e.printStackTrace();
}
if (telephony.getCallState() == 1)
flag = 1;
Log.d("Rec", "reciever");
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
callingscreen("1", context, intent);
}
}
};
pageTimer.start();
}
public void callingscreen(final String type, final Context context,
final Intent intent) {
Intent intentPhoneCall = new Intent(context.getApplicationContext(),
CallerScreen.class);
intentPhoneCall.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
intentPhoneCall.putExtra(
"number",
intent.getExtras().getString(
TelephonyManager.EXTRA_INCOMING_NUMBER));
intentPhoneCall.putExtra("type", type);
context.startActivity(intentPhoneCall);
}
} // class
Problem
But the Problem is that this popup is showing over the default calling screen. What I want to show the popup on the user current screen on which he was working.
Question
So the simple question is that how can I get the user current screen with its all functionality below the popup?
Please help:)
This solution works on every version of android, including lollipop
Use this broadcast reciever
class TeleListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
// CALL_STATE_IDLE;
Toast.makeText(getApplicationContext(), "CALL_STATE_IDLE",
Toast.LENGTH_LONG).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
// CALL_STATE_OFFHOOK;
Toast.makeText(getApplicationContext(), "CALL_STATE_OFFHOOK",
Toast.LENGTH_LONG).show();
break;
case TelephonyManager.CALL_STATE_RINGING:
// CALL_STATE_RINGING, call intent here
Intent i = null;
i = new Intent(context, My_activity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
break;
default:
break;
}
}
}
and register it like this in onCreate
TelephonyManager TelephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
TelephonyMgr.listen(new TeleListener(), PhoneStateListener.LISTEN_CALL_STATE);
And yes, please dont miss
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Cheers! Your problems is solved ;)
Related
I'm developing an app that will only be used in house for testing purpose. I have searched a lot and tried different suggestions as suggested in different post but none seems to be working for me.
I'm open to any suggestions like Reflections, Accessibility Service, root or any other hack. Please help.
Regards
TRY THIS
Set all required permission in manifest.xml file.
Call this class in Service
public class PhoneListener extends PhoneStateListener {
private static PhoneListener instance = null;
/**
* Must be called once on app startup
*
* #param context - application context
* #return
*/
public static PhoneListener getInstance(Context context) {
if (instance == null) {
instance = new PhoneListener(context);
}
return instance;
}
public static boolean hasInstance() {
return null != instance;
}
private final Context context;
private CallLog phoneCall;
private PhoneListener(Context context) {
this.context = context;
}
AtomicBoolean isRecording = new AtomicBoolean();
AtomicBoolean isWhitelisted = new AtomicBoolean();
/**
* Set the outgoing phone number
* <p/>
* Called by {#link MyCallReceiver} since that is where the phone number is available in a outgoing call
*
* #param phoneNumber
*/
public void setOutgoing(String phoneNumber) {
if (null == phoneCall)
phoneCall = new CallLog();
phoneCall.setPhoneNumber(phoneNumber);
phoneCall.setOutgoing();
// called here so as not to miss recording part of the conversation in TelephonyManager.CALL_STATE_OFFHOOK
isWhitelisted.set(Database.isWhitelisted(context, phoneCall.getPhoneNumber()));
}
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: // Idle... no call
if (isRecording.get()) {
RecordCallService.stopRecording(context);
phoneCall = null;
isRecording.set(false);
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK: // Call answered
if (isWhitelisted.get()) {
isWhitelisted.set(false);
return;
}
if (!isRecording.get()) {
isRecording.set(true);
// start: Probably not ever usefull
if (null == phoneCall)
phoneCall = new CallLog();
if (!incomingNumber.isEmpty()) {
phoneCall.setPhoneNumber(incomingNumber);
}
// end: Probably not ever usefull
RecordCallService.sartRecording(context, phoneCall);
}
break;
case TelephonyManager.CALL_STATE_RINGING: // Phone ringing
// DO NOT try RECORDING here! Leads to VERY poor quality recordings
// I think something is not fully settled with the Incoming phone call when we get CALL_STATE_RINGING
// a "SystemClock.sleep(1000);" in the code will allow the incoming call to stabilize and produce a good recording...(as proof of above)
if (null == phoneCall)
phoneCall = new CallLog();
if (!incomingNumber.isEmpty()) {
phoneCall.setPhoneNumber(incomingNumber);
// called here so as not to miss recording part of the conversation in TelephonyManager.CALL_STATE_OFFHOOK
isWhitelisted.set(Database.isWhitelisted(context, phoneCall.getPhoneNumber()));
}
break;
}
}
}
And use Broadcast Receiver
public class MyCallReceiver extends BroadcastReceiver {
public MyCallReceiver() {
}
static TelephonyManager manager;
#Override
public void onReceive(Context context, Intent intent) {
Log.i("JLCreativeCallRecorder", "MyCallReceiver.onReceive ");
if (!AppPreferences.getInstance(context).isRecordingEnabled()) {
removeListener();
return;
}
if (Intent.ACTION_NEW_OUTGOING_CALL.equals(intent.getAction())) {
if (!AppPreferences.getInstance(context).isRecordingOutgoingEnabled()) {
removeListener();
return;
}
PhoneListener.getInstance(context).setOutgoing(intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
} else {
if (!AppPreferences.getInstance(context).isRecordingIncomingEnabled()) {
removeListener();
return;
}
}
// Start Listening to the call....
if (null == manager) {
manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
}
if (null != manager)
manager.listen(PhoneListener.getInstance(context), PhoneStateListener.LISTEN_CALL_STATE);
}
private void removeListener() {
if (null != manager) {
if (PhoneListener.hasInstance())
manager.listen(PhoneListener.getInstance(null), PhoneStateListener.LISTEN_NONE);
}
}
}
I hope you get some help from this code.
Thanks
You can use accessibility events to detect the call duration and from that you can detect if the outgoing call is answered or not..
I have answered it in detail in Here` you can check that.
You need this permission in manifest
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
TelephonyManager has a listener to get phone state. implement this tho know if the phone is ringing or in a call.
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener callStateListener = new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber) {
// TODO React to a incoming call.
try {
if (state == TelephonyManager.CALL_STATE_RINGING) {
Toast.makeText(getApplicationContext(), "Phone Is Ringing" + incomingNumber, Toast.LENGTH_LONG).show();
number = incomingNumber;
//g.setPhoneNo(incomingNumber);
AndroidNetCommunicationClientActivity.mMsgSendRequest("CommandMsgCallIncoming" + number);
} else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
Toast.makeText(getApplicationContext(), "Phone is Currently in A call" + incomingNumber, Toast.LENGTH_LONG).show();
//number = mIntent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
number = incomingNumber;
} else if (state == TelephonyManager.DATA_DISCONNECTED) {
number = "";
CallID = "";
}
} catch (Exception e) {
// TODO Auto-generated catch block
//conn.MessageBox(MainActivity.this, e.getMessage());
e.printStackTrace();
}
super.onCallStateChanged(state, incomingNumber);
}
};
telephonyManager.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE);
I want to disconnect incoming call for a particular time.
How can i do this is it impossible ?
I searched and i find it is impossible. please help me.
public class Telephony3 extends Service
{
Context context;
public IBinder onBind(Intent intent)
{
return null;
}
public void onCreate()
{
super.onCreate();
try
{
StateListener phoneStateListener = new StateListener();
TelephonyManager telephonymanager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
telephonymanager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}catch(Exception e)
{
e.printStackTrace();
}
}
class StateListener extends PhoneStateListener{
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
//Disconnect the call here...
try{
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
Class c = Class.forName(manager.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
ITelephony telephony = (ITelephony)m.invoke(manager);
telephony.endCall();
}catch(Exception e){
Log.d("",e.getMessage());
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
case TelephonyManager.CALL_STATE_IDLE:
break;
}
}
};
public void onDestroy()
{
}
}
///////////////////////////////////////////
make another package com.android.internal.telephony and make one interface ITelephony
public interface ITelephony
{
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
and when i call this emulator from another the calling is happening. any thing wrong here please suggest me.
thanks in advance
You can generate your own activity that handles action "ACTION_ANSWER".
Register your application component as a intent handler.
Here is a blog post which suggest a possible workaround.
Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
getContext().sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");
from
http://androidbridge.blogspot.com/2011/05/how-to-answer-incoming-call-in-android.html
I want to perform some operation (Pause game) in my application when a call came. But reading the phone state is not working. I have given permission(READ_PHONE_STATE) in the manifest. Nothing is happen when a call came.
Thanks.
TelephonyManager telephonyManager;
PhoneStateListener listener;
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
*
*
*
listener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Toast.makeText(SudokuGameActivity.this, "IDLE", Toast.LENGTH_SHORT).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Toast.makeText(SudokuGameActivity.this, "OFF Hook", Toast.LENGTH_SHORT).show();
break;
case TelephonyManager.CALL_STATE_RINGING:
Toast.makeText(SudokuGameActivity.this, "Ringing", Toast.LENGTH_SHORT).show();
mpauseButton.performClick();
break;
}
}
};
Have you written the following line :
telephonyManager.listen(listener,PhoneStateListener.LISTEN_CALL_STATE);
when your listener has be created, you need invoke `public void listen (PhoneStateListener listener, int events)' to listen.
also, you can try this:
create a broadcatst receiver handle the action android.intent.action.PHONE_STATE,
code example:
public class PhoneStateReceiver extends BroadcastReceiver {
private TelephonyManager manager;
#Override
public void onReceive(Context context, Intent intent) {
if (manager == null) {
manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
}
String action = intent.getAction();
System.out.println(action);
System.out.println("current phone state:" + manager.getCallState());
}
}
I have this code to receive the caller number and do query in side case TelephonyManager.CALL_STATE_RINGING
I already get the caller number but when i want to do query in side the case the app will give me error i don't know why can any one help me please to solve the problem
this is my code
public class IncomingCallReciever extends BroadcastReceiver {
protected static final String TAG = "SWAJ";
private Context mContext;
private Intent mIntent;
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG ," onCallStateChanged ");
mContext = context;
mIntent = intent;
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
int events = PhoneStateListener.LISTEN_CALL_STATE;
tm.listen(phoneStateListener, events);
}
private final PhoneStateListener phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
SilentMeDB databaseHelper = new SilentMeDB(mContext);
SQLiteDatabase db = databaseHelper.getReadableDatabase();
Cursor c = db.query("events",null,null, null, null, null, null);
c.moveToFirst();
while(!c.isAfterLast())
{
try
{
Log.d(TAG, "Message is " + c.getString(c.getColumnIndex("Message") ));
}
catch(Exception e)
{
Log.d("Exp", e.getMessage());
}
c.moveToNext();
} c.close();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
}
super.onCallStateChanged(state, incomingNumber);
}
};
}
I think you want to move query code up into the on receive method. I don't see any reason to be using a listener here. Besides, the moment your onReceive function ends that listener is going to go away and won't be listening anymore. In your onReceive you can check the Intent you get to see if the call state is ringing and then conditionally execute your code.
I am trying to use BroadcastReceiver to receive incoming calls. I want to register call when the call is ended. Below code gives each state (idle,ringing n offhook) more than once with the same number (its not an issue of past call). Is it because phonestatelistner is called within the service.
public class IncomingCallReceiver extends BroadcastReceiver {
int stateString =0;
int prevStat = 0;
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(null == bundle)
return;
String state = bundle.getString(TelephonyManager.EXTRA_STATE);
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING))
{
String phonenumber = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
String info = "Detect Calls sample application\nIncoming number: " + phonenumber;
Toast.makeText(context, info, Toast.LENGTH_LONG).show();
}
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
//CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();
PhoneStateListener listener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
String p = incomingNumber;
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
prevStat = stateString;
stateString = 1;
Log.i("ON CALL STATE CHANGED","IDLE");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.i("ON CALL STATE CHANGED","OFFFHOOK");
prevStat = stateString;
stateString = 2;
break;
case TelephonyManager.CALL_STATE_RINGING:
prevStat = stateString;
stateString = 3;
Log.i("ON CALL STATE CHANGED","RINGING");
break;
}
if(prevStat == 2 && stateString == 1)
{
Log.i("REGISTER A CALLL","==" +p);
}
}
};
telephony.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
I also tried the same thing with phonestatelistener in a separate class, but it was not being called, i.e my code didn't reach there. In my manifest file I have registered receiver, but there is no declaration of phonestatelistener. Is that to be registered?
I am sorry if the solution is quite obvious but am new to android things.
Any help is appreciated :)
Yes, choose listener or received , not both of them