3

Following is my code in which I am using reflection to access com.android.internal.telephony.CallManager .I am using its function GetActiveFGCallState() to get different state like Alerting for outgoing calls, But it keeps on returning me idle state even if the state is OFF_HOOK or RINGING.So What I understand from this is that My call is not in foreground because the state of active foreground call return IDLE if there is no active foreground call. So is my understanding correct ? If Yes then how to bring call activity to foreground and if no then what might be the problem?

Main Activity Code:

package com.example.misscall;


import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.Menu;

public class MainActivity extends Activity {
     final Context context = this;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent callIntent = new Intent(Intent.ACTION_CALL,
                Uri.parse("tel:" + "03365188508"));
        callIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        startActivity(callIntent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

Mainfiest File:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.misscall"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />
    <uses-feature android:name="android.hardware.telephony">
    </uses-feature>
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

            <receiver android:name="com.example.misscall.DataConnection">
        <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE"/>     
        </intent-filter>
</receiver>
        <activity
            android:name="com.example.misscall.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Data Connection Class

    import android.os.RemoteException;
    import android.telephony.PhoneStateListener;
    import android.telephony.TelephonyManager;
    import android.util.Log;
    import android.widget.Toast;

    public class DataConnection extends BroadcastReceiver {
        TelephonyManager Tm;
         ITelephony telephonyService;
         Class c = null;
         Method methodGetInstance = null;
         Method methodGetActiveFgCallState=null;
         String TAG="Tag";
         Object objectCallManager=null;
        @Override
        public void onReceive(final Context context, Intent intent) {

            Tm=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
            final ClassLoader classLoader = this.getClass().getClassLoader();
            try {
                final Class<?> classCallManager = classLoader.loadClass("com.android.internal.telephony.CallManager");
                Log.e(TAG, "CallManager: Class loaded " + classCallManager.toString());

                 methodGetInstance = classCallManager.getDeclaredMethod("getInstance");
                methodGetInstance.setAccessible(true);
                Log.e(TAG, "CallManager: Method loaded " + methodGetInstance.getName());

                 objectCallManager = methodGetInstance.invoke(null);
                Log.e(TAG, "CallManager: Object loaded " + objectCallManager.getClass().getName());

                Method[] aClassMethods = classCallManager.getDeclaredMethods();  
                for(Method m : aClassMethods)  
                {  
                    Log.e("MEthods",m.getName());  
                }
                 methodGetActiveFgCallState = classCallManager.getDeclaredMethod("getActiveFgCallState");
                Log.e(TAG, "CallManager: Method loaded " + methodGetActiveFgCallState.getName());

                Log.e(TAG, "CallManager: What is the Call state = " + methodGetActiveFgCallState.invoke(objectCallManager));
            }
            catch (ClassNotFoundException e) {
                Log.e(TAG, e.getClass().getName() + e.toString());
            }
            catch (NoSuchMethodException e) {
                Log.e(TAG, e.getClass().getName() + e.toString());
            }
            catch (InvocationTargetException e) {
                Log.e(TAG, e.getClass().getName() + e.toString());
            }
            catch (IllegalAccessException e) {
                Log.e(TAG, e.getClass().getName() + e.toString());
            }
            Tm.listen(new PhoneStateListener(){
                public void  onCallStateChanged(int state,String number) {
                    super.onCallStateChanged(state, number);

                     try {
                        if (methodGetActiveFgCallState.invoke(objectCallManager).toString().toLowerCase() .equals("idle"))
                         {
                             Toast.makeText(context, "I am in idle state", Toast.LENGTH_LONG).show();
                         }
                    } catch (IllegalArgumentException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }

            },PhoneStateListener.LISTEN_CALL_STATE);


        }

    }
user2137186
  • 817
  • 6
  • 22
  • 39
  • What you want, to get call state only? Right? – TheLittleNaruto Oct 30 '13 at 05:15
  • @TheLittleNaruto ...What I want to know is when other person picked up the call or when his/her mobile started ringing...Which I can get from alerting state..So I want to Get that Alerting State – user2137186 Oct 30 '13 at 05:22

2 Answers2

2

Please try below:

    PhoneStateListener callStateListener = new PhoneStateListener() {
            public void onCallStateChanged(int state, String incomingNumber) 
            {
                  if(state==TelephonyManager.CALL_STATE_RINGING)
                    {
                            Toast.makeText(getApplicationContext(),"Phone Is Riging", Toast.LENGTH_LONG).show();

                    }
                    if(state==TelephonyManager.CALL_STATE_OFFHOOK)
                    {
                        Toast.makeText(getApplicationContext(),"Phone is Currently in A call", Toast.LENGTH_LONG).show();
                    }

                    if(state==TelephonyManager.CALL_STATE_IDLE)
                    {
                        Toast.makeText(getApplicationContext(),"phone is neither ringing nor in a call", Toast.LENGTH_LONG).show();
                    }
            }
            };


telephonyManager.listen(callStateListener,PhoneStateListener.LISTEN_CALL_STATE);

Reference.

halfer
  • 19,824
  • 17
  • 99
  • 186
TheLittleNaruto
  • 8,325
  • 4
  • 54
  • 73
  • I want this for outgoing calls not for incoming calls – user2137186 Oct 30 '13 at 05:36
  • Man, It's for outgoing call. If you'll make a call from your device, it'll notify you. try this. – TheLittleNaruto Oct 30 '13 at 05:40
  • I have already try this and for the sake of information Ringing state is not for outgoing calls.Only OFF_HOOK and IDLE State works in the case of outgoing calls.OFF_HOOK State is activated when you press the dial button and IDLE state gets activated when Call is disconnected .So to know if the person you are calling answered you or if his/her mobile is ringing, you need to use internal api which can be used by reflection or by changing in IDE files .I am using the reflection method to access this CALLManager API ...remaining in next comment – user2137186 Oct 30 '13 at 05:47
  • (Remaining Part)..I am able to access its GetActiveFGCallState() which is used to return state..More details on states here:http://stackoverflow.com/questions/6290347/what-does-the-different-call-states-in-the-android-telephony-stack-represent.The problem which I am facing is that it always return me the idle state no matter what the call state is – user2137186 Oct 30 '13 at 05:49
1
<receiver android:name=".OutgoingCallReceiver">
        <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE"/>     
        </intent-filter>
</receiver>



    public class OutgoingCallReceiver extends BroadcastReceiver {
        private static long timeStarted = -1L; // IMPORTANT!

        private static String number;
        private static boolean noCallListenerYet = true;

        @Override
        public void onReceive(final Context context, Intent intent) {
            PhoneCallListener phoneListener = new PhoneCallListener(context);
            TelephonyManager telephonyManager = (TelephonyManager) context
                    .getSystemService(Context.TELEPHONY_SERVICE);
            telephonyManager.listen(phoneListener,
                    PhoneStateListener.LISTEN_CALL_STATE);
        }

        private class PhoneCallListener extends PhoneStateListener {
            Context context;
            private boolean isPhoneCalling = false;

            public PhoneCallListener(Context context2) {
                // TODO Auto-generated constructor stub
                context=context2;
            }

            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
                //do something here
                }

                if (state == TelephonyManager.CALL_STATE_IDLE && timeStarted != -1L) {}
            }
        }
    }
KOTIOS
  • 11,177
  • 3
  • 39
  • 66