I am trying to get a phone object so that I can call and conference two numbers from within my application.
I have tried using the static PhoneFactory.makeDefa
Al least we can answer or ignore calls =) let me copy-paste my post
OMG!!! YES, WE CAN DO THAT!!!
I was going to kill myself after severe 24 hours of investigating and discovering... But I've found a "fresh" solution!
// "cheat" with Java reflection to gain access
// to TelephonyManager's ITelephony getter
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
telephonyService = (ITelephony)m.invoke(tm);
People who want to develop their call-control software visit this start point: http://www.google.com/codesearch/p?hl=en#zvQ8rp58BUs/trunk/phone/src/i4nc4mp/myLock/phone/CallPrompt.java&q=itelephony%20package:http://mylockforandroid%5C.googlecode%5C.com&d=0
There is a project. and there are important comments (and credits).
In short: copy AIDL file, add permissions to manifest, copy-paste source for telephony management.
Some more info for you. AT commands you can send only if you are rooted. Than you can kill system process and send commands but you will need a reboot to allow your phone to receive and send calls.
I'm very happy! =) Now my Shake2MuteCall will get an update !
Yes it can be instantiated. But you have to overcome a couple of hurdles:
In your AndroidManifest.xml set
android:sharedUserId="android.uid.phone"
within the <manifest> tag. This is required to prevent a SecurityException from being thrown when protected Intents are sent by the methods you may invoke (like android.intent.action.SIM_STATE_CHANGED).
Set
android:process="com.android.phone"
in your <application> tag. This is required to allow the invocation of getDefaultPhone() / makeDefaultPhone().
To do all this your app must be signed with the system signature key.
Fyi, the internal classes Phone, CallManager and some more are moved from /system/framework/framework.jar to /system/framework/telephony-common.jar in Jelly bean.
Hy. I was able to retrieve an ProxyPhone trought this class ( and a little bit of reflection ). You may use the (Reflected)PhoneFactory below:
package your.package;
import java.lang.reflect.Method;
import android.content.Context;
import android.util.Log;
public class ReflectedPhoneFactory {
public static final String TAG = "PHONE";
public static void makeDefaultPhones(Context context) throws IllegalArgumentException {
try{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class PhoneFactory = cl.loadClass("com.android.internal.telephony.PhoneFactory");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[1];
paramTypes[0]= Context.class;
Method get = PhoneFactory.getMethod("makeDefaultPhone", paramTypes);
//Parameters
Object[] params= new Object[1];
params[0]= context;
get.invoke(null, params);
}catch( IllegalArgumentException iAE ){
throw iAE;
}catch( Exception e ){
Log.e(TAG, "makeDefaultPhones", e);
}
}
public static void makeDefaultPhone(Context context) throws IllegalArgumentException {
try{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class PhoneFactory = cl.loadClass("com.android.internal.telephony.PhoneFactory");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[1];
paramTypes[0]= Context.class;
Method get = PhoneFactory.getMethod("makeDefaultPhone", paramTypes);
//Parameters
Object[] params= new Object[1];
params[0]= context;
get.invoke(null, params);
}catch( IllegalArgumentException iAE ){
throw iAE;
}catch( Exception e ){
Log.e(TAG, "makeDefaultPhone", e);
}
}
/*
* This function returns the type of the phone, depending
* on the network mode.
*
* @param network mode
* @return Phone Type
*/
public static Integer getPhoneType(Context context, int networkMode) throws IllegalArgumentException {
Integer ret= -1;
try{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class PhoneFactory = cl.loadClass("com.android.internal.telephony.PhoneFactory");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[1];
paramTypes[0]= Integer.class;
Method get = PhoneFactory.getMethod("getPhoneType", paramTypes);
//Parameters
Object[] params= new Object[1];
params[0]= new Integer(networkMode);
ret= (Integer) get.invoke(PhoneFactory, params);
}catch( IllegalArgumentException iAE ){
throw iAE;
}catch( Exception e ){
ret= -1;
}
return ret;
}
public static Object getDefaultPhone(Context context) throws IllegalArgumentException {
Object ret= null;
try{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class PhoneFactory = cl.loadClass("com.android.internal.telephony.PhoneFactory");
Method get = PhoneFactory.getMethod("getDefaultPhone", (Class[]) null);
ret= (Object)get.invoke(null, (Object[]) null);
}catch( IllegalArgumentException iAE ){
throw iAE;
}catch( Exception e ){
Log.e(TAG, "getDefaultPhone", e);
}
return ret;
}
public static Phone getCdmaPhone(Context context) throws IllegalArgumentException {
Phone ret= null;
try{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class PhoneFactory = cl.loadClass("com.android.internal.telephony.PhoneFactory");
Method get = PhoneFactory.getMethod("getCdmaPhone", (Class[]) null);
ret= (Phone)get.invoke(null, (Object[]) null);
}catch( IllegalArgumentException iAE ){
throw iAE;
}catch( Exception e ){
//
}
return ret;
}
public static Phone getGsmPhone(Context context) throws IllegalArgumentException {
Phone ret= null;
try{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class PhoneFactory = cl.loadClass("com.android.internal.telephony.PhoneFactory");
Method get = PhoneFactory.getMethod("getGsmPhone", (Class[]) null);
ret= (Phone)get.invoke(null, (Object[]) null);
}catch( IllegalArgumentException iAE ){
throw iAE;
}catch( Exception e ){
//
}
return ret;
}
}
With it, use the code:
ReflectedPhoneFactory.makeDefaultPhone(yourContext);
Object phoneProxy= ReflectedPhoneFactory.getDefaultPhone(yourContext);
Note that the "makeDefaultPhone" call will update the value of the static member "static private Looper sLooper;" and i did not yet tested for collateral effects.
With the received "phoneProxy" object you may make the PhoneProxy call´s trought reflection. ( I am currently implementing this class and may post it if considered useful.
I am trying to get a phone object so that I can call and conference two numbers from within my application.
That is not possible from the SDK.
I have tried using the static PhoneFactory.makeDefaultPhones((Context)this) but have not had any luck.
That is not in the SDK. Please do not go past the bounds of the SDK.
Error - Caused by java.lang.RuntimeException: PhoneFactory.getDefaultPhone must be called from Looper thread
That is because you are trying to do the thing-you're-not-supposed-to-be-doing from a background thread.
I called it from Activity.onCreate and it crashed several lines after your problem with the following error:
Default phones haven't been made yet!
See the Android sources:
public static Phone getDefaultPhone() {
if (sLooper != Looper.myLooper()) {
throw new RuntimeException(
"PhoneFactory.getDefaultPhone must be called from Looper thread");
}
if (!sMadeDefaults) {
throw new IllegalStateException("Default phones haven't been made yet!");
}
return sProxyPhone;
}