场景:
接管系统的拨号盘及电话应用,需要拨打如中国移动等运营商时能发送数字按键指令。(mtk的手机方案)
参考文档:
需要权限:
系统权限及系统签名
在AndroidManifest.xml里增加
android:sharedUserId="android.uid.phone" 或 android:sharedUserId="android.uid.system"
遇到的问题:
由于我们定制了拨号界面,里面有很多交互逻辑以及第三方依赖,不可能将这个页面单独设置为android:process="com.android.phone"进程,但发送dtmf又必须在这个进程中。
解决方案:
单独将发送dtmf的功能独立到com.android.phone进程的service中
package ***.service;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import java.lang.reflect.Method;
public class DtmfSendService extends Service {
private String ACTION_SEND_DTMF = "net.bonvo.client.bonvobox.send_dtmf";
private String TAG = "DtmfSendService";
private SendDtmfReceiver mReceiver;
@Override
public void onCreate() {
super.onCreate();
registerReceiver();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
if (mReceiver != null) {
unregisterReceiver(mReceiver);
}
}
private void registerReceiver() {
mReceiver = new SendDtmfReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_SEND_DTMF);
registerReceiver(mReceiver, filter);
}
public void sendDtmf(char keycode) {
//https://blog.csdn.net/jinliang_890905/article/details/43458877
//https://www.cnblogs.com/IT-Goddess/p/5725705.html
//https://stackoverflow.com/questions/4745899/how-to-access-com-android-internal-telephony-callmanager
//源码:http://androidxref.com/9.0.0_r3/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/CallManager.java#1216
try {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
final Class<?> classCallManager = classLoader.loadClass("com.android.internal.telephony.CallManager");
Log.i(TAG, "Class loaded " + classCallManager.toString());
Method methodGetInstance = classCallManager.getDeclaredMethod("getInstance");
Log.i(TAG, "Method loaded " + methodGetInstance.getName());
Object objectCallManager = methodGetInstance.invoke(null);
Log.i(TAG, "Object loaded " + objectCallManager.getClass().getName());
Method methodSendDtmf = classCallManager.getDeclaredMethod("sendDtmf", char.class);
methodSendDtmf.setAccessible(true);
Log.i(TAG, "Method loaded " + methodSendDtmf.getName());
Log.i(TAG, "SendDtmf = " + methodSendDtmf.invoke(objectCallManager, keycode));
} catch (Exception e) {
e.printStackTrace();
}
}
class SendDtmfReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null && intent.getAction().contentEquals(ACTION_SEND_DTMF)) {
char code = intent.getCharExtra("dtmfCode",'-');
if (code != '-') {
Log.e(TAG,"发送dtmf=" + code);
sendDtmf(code);
}
}
}
}
}
清单文件中申明service
<service android:name="***.service.DtmfSendService"
android:process="com.android.phone" />
使用方法:
1、在通话界面先启动startService
2、需要发送指令时发送
Intent dtmfIntent = new Intent();
dtmfIntent.setAction(CustomAction.SEND_DTMF);
dtmfIntent.putExtra("dtmfCode",key);
sendBroadcast(dtmfIntent);
网友评论