Android中通过拨号调起应用的实现方式及特殊情况处理
Android中有时我们会有这样的需求:通过拨号调起我们的程序。这个需求如何实现呢?
思路当然是在我们的应用中实现一个广播接收器(BroadcastReceiver),对打电话时系统发出的广播进行拦截。
实现步骤:
1、在AndroidMainfest.xml中添加权限:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
2、实现拨号广播接收器:
public class LaunchAppViaDialReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) { Bundle bundle = intent.getExtras(); if (null == bundle) return; String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); if (phoneNumber.equals("1234")) { setResultData(null); abortBroadcast(); Intent appIntent = new Intent(context, MainActivity.class); appIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(appIntent); } } } }
3、在AndroidMainfest.xml中注册广播接收器
<receiver android:name=".LaunchAppViaDialReceiver" android:enabled="true" android:exported="true"> <intent-filter android:priority="1000"> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> </intent-filter> </receiver>
本以为大功告成,但在测试过程中发现不同手机出现了不同效果:
小米4拨号后可以正常调起应用(电话没有拨打出去)
华为荣耀6、htc one拨号后会开始打电话(当然是空号),电话挂断后应用正常调起
魅族mx3拨号后开始打电话(是空号),电话挂断后应用不会调起(收不到打电话的广播)
显然这个方式不完美,那么还有没有其他办法呢?
经过一番摸索,最终实现了手头有的机型都可以正常调起应用(有的在挂掉电话后才能调起)。
实现方案就是读取用户最后一条通话记录,对号码进行判断,如果是我们期望的号码就调起我们的应用。
这种方式依然不够完美(需要增加读取通话记录权限),但功能基本达到可用状态。
实现方案:
1、在AndroidMainfest.xml中添加权限:
<uses-permission android:name="android.permission.READ_CALL_LOG" />
2、实现通话观察服务类:
public class CallAppService extends Service { private static final String TAG = "CallAppService"; private final Handler mHandler = new MyHandler(this); static class MyHandler extends Handler { private final WeakReference<CallAppService> mService; public MyHandler(CallAppService service) { mService = new WeakReference<>(service); } @Override public void handleMessage(Message msg) { CallAppService service = mService.get(); if (service != null) { service.handleMessage(msg); } } } @SuppressWarnings("UnusedParameters") private void handleMessage(Message msg) { Intent appIntent = new Intent(this, MainActivity.class); appIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(appIntent); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand"); getAllCallLogs(); return START_STICKY; } @Nullable @Override public IBinder onBind(Intent intent) { return null; } private void getAllCallLogs() { Uri mediaUri = android.provider.CallLog.Calls.CONTENT_URI; getContentResolver().registerContentObserver(mediaUri, false, new CustomContentObserver(mHandler)); } class CustomContentObserver extends ContentObserver { private final Handler handler; public CustomContentObserver(Handler handler) { super(handler); this.handler = handler; } @Override public boolean deliverSelfNotifications() { return false; } public void logCallLog() { String columns[] = new String[]{ CallLog.Calls._ID, CallLog.Calls.NUMBER, CallLog.Calls.DATE, CallLog.Calls.DURATION, CallLog.Calls.TYPE}; Cursor c; c = getContentResolver().query(Uri.parse("content://call_log/calls"), columns, null, null, "Calls._ID DESC"); //last record first while (c != null && c.moveToNext()) { String number = c.getString(c.getColumnIndex(CallLog.Calls.NUMBER)); if (number.equals("1234")) { this.handler.obtainMessage().sendToTarget(); } else { return; } } if (c != null) { c.close(); } } @Override public void onChange(boolean selfChange){ super.onChange(selfChange); logCallLog(); } } }
3、在AndroidManifest.xml中注册服务:
<service android:name=".service.CallAppService" />
4、在应用启动后启动服务:
startService(new Intent(MainActivity.this, CallAppService.class));
以上就是目前的方案,如果大家有更好的方案,欢迎交流。