• 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));

    以上就是目前的方案,如果大家有更好的方案,欢迎交流。

  • 相关阅读:
    Qt模拟C#的File类对文件进行操作
    Qt Creator (C++)保存文件
    winfrom LED时钟
    winfrom 水晶按钮
    C#语言的Image和byte数组的互相转换
    GDI+ 绘图闪烁解决方法
    vue webpack 架构下使用 bootstrap 的模态框modal 做遮罩效果组件及应用
    windows 版Tomcat 7.0的配置
    转:说说JSON和JSONP
    HttpWebRequest在GetResponse时总是超时
  • 原文地址:https://www.cnblogs.com/lurenjiashuo/p/android-call-app-from-dial.html
Copyright © 2020-2023  润新知