Может ли объект telephony.Phone быть создан через sdk?
Я пытаюсь получить объект телефона, чтобы я мог звонить и отправлять по телефону два номера из моего приложения.
Я попытался использовать статический PhoneFactory.makeDefaultPhones((Context)this)
, но не повезло.
String phoneFactoryName = "com.android.internal.telephony.PhoneFactory";
String phoneName = "com.android.internal.telephony.Phone";
Class phoneFactoryClass = Class.forName(phoneFactoryName);
Class phoneClass = Class.forName(phoneName);
Method getDefaultPhone = phoneFactoryClass.getMethod("getDefaultPhone");
Object phoneObject = getDefaultPhone.invoke(null);
Ошибка - вызвано java.lang.RuntimeException: PhoneFactory.getDefaultPhone должен быть вызван из потока Looper
Ответы
Ответ 1
Да, он может быть создан. Но вам нужно преодолеть пару препятствий:
-
В вашем AndroidManifest.xml
установите
Android: sharedUserId = "android.uid.phone"
в теге <manifest>
. Это необходимо для предотвращения выброса SecurityException
, когда защищенные намерения отправляются с помощью методов, которые вы можете вызвать (например, android.intent.action.SIM_STATE_CHANGED
).
-
Set
Android: процесс = "com.android.phone"
в тэге <application>
. Это необходимо для вызова getDefaultPhone()
/makeDefaultPhone()
.
-
Чтобы сделать все это, ваше приложение должно быть подписано с ключом подписи системы.
Ответ 2
По крайней мере, мы можем ответить или проигнорировать вызовы =) позвольте мне скопировать вставить мой пост
OMG!!! ДА, МЫ МОЖЕМ СДЕЛАТЬ, ЧТО!!!
Я собирался убить себя после суровых 24 часов расследования и обнаружения... Но я нашел "новое" решение!
// "cheat" with Java reflection to gain access
// to TelephonyManager ITelephony getter
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
telephonyService = (ITelephony)m.invoke(tm);
Люди, которые хотят разработать свое программное обеспечение для управления вызовами, заходят в эту начальную точку:
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
Есть проект. и есть важные комментарии (и кредиты).
Вкратце: скопируйте файл AIDL, добавьте разрешения для манифеста, скопируйте источник для управления телефонией.
Дополнительная информация для вас. AT-команды, которые вы можете отправить, только если вы укоренились. Чем вы можете убить системный процесс и отправить команды, но вам потребуется перезагрузка, чтобы ваш телефон мог принимать и отправлять вызовы.
Я очень счастлив! =) Теперь мой Shake2MuteCall получит обновление!
Ответ 3
Hy. Я смог получить ProxyPhone, вызвавший этот класс (и немного отражения). Вы можете использовать (Reflected) PhoneFactory ниже:
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;
}
}
С ним используйте код:
ReflectedPhoneFactory.makeDefaultPhone(yourContext);
Object phoneProxy= ReflectedPhoneFactory.getDefaultPhone(yourContext);
Обратите внимание, что вызов "makeDefaultPhone" обновит значение статического члена "статический закрытый Looper sLooper"; и я еще не тестировал побочные эффекты.
С полученным объектом "phoneProxy" вы можете сделать отражение звонка PhoneProxy. (Я в настоящее время реализую этот класс и могу опубликовать его, если сочтет это полезным.
Ответ 4
Я пытаюсь получить объект телефона так что я могу позвонить и провести конференцию два номера из моей заявки.
Это невозможно из SDK.
Я попытался использовать статический PhoneFactory.makeDefaultPhones((контекст) это) но не повезло.
Это не в SDK. Пожалуйста, не следует за границами SDK.
Ошибка - вызвана java.lang.RuntimeException: PhoneFactory.getDefaultPhone должен быть вызванный из потока Looper
Это потому, что вы пытаетесь сделать то, что вам не нужно делать из фонового потока.
Ответ 5
Я вызвал его из Activity.onCreate и он разбил несколько строк после вашей проблемы со следующей ошибкой:
Телефоны по умолчанию еще не созданы!
Смотрите источники Android:
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;
}
Ответ 6
Fyi, внутренние классы Phone, CallManager и некоторые другие перемещаются из /system/framework/framework.jar в/system/framework/telephony-common.jar в Jelly bean.