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

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

Android中通过拨号调起应用的实现方式及特殊情况处理的更多相关文章

  1. Android中H5和Native交互的两种方式

    Android中H5和Native交互的两种方式:http://www.jianshu.com/p/bcb5d8582d92 注意事项: 1.android给h5页面注入一个对象(WZApp),这个对 ...

  2. Android中多线程编程(三)Handler更新UI的方式

    Handler更新UI的方式和原因以及遇到的问题 1.方式: 仅仅能通过Handler来更新UI. 代码例如以下: package com.chengdong.su.handlerdemo; impo ...

  3. android中实现拨号功能

    1.要实现拨号功能,首先需要开启拨号权限 修改AndroidManifest.xml文件,添加如下内容: <uses-permission android:name="android. ...

  4. Android中设置控件的背景颜色的方式整理

    版权声明:本文为博主原创文章,未经博主允许不得转载. 前言 在Android开发中,经常需要设置控件的背景颜色或者图片的src颜色. 效果图 代码分析 根据使用的方法不同,划分为 setBackgro ...

  5. Android中Button四种点击事件实现方式

    1.Xml添加监听属性,这里添加的doClick. <Button android:id="@+id/bt1" android:layout_width="wrap ...

  6. Android中对应用程序的行为拦截实现方式概要

    这次是真的好长时间都没有写博客了,主要不是因为工作上的事,主要还是这个问题真的有点复杂,实现起来有点麻烦,所以研究了很长时间(大约有一个月的时间).但是幸好最后问题搞定了~~ 一.问题场景 想实现36 ...

  7. Android中实现短信发送的一种方式

    SendSmsActivity.java: package com.test.smsmangerdemo.sendsmsactivity; import android.support.v7.app. ...

  8. Android中服务的生命周期与两种方式的区别

    服务的生命周期跟Activity的生命周期类似.但是生命周期甚至比你关注服务如何创建和销毁更重要,因为服务能够在用户不知情的情况下在后台运行. 服务的生命周期---从创建到销毁---可以被分为以下两个 ...

  9. 在web项目中获取ApplicationContext上下文的3种主要方式及适用情况

    最近在做web项目,需要写一些工具方法,涉及到通过Java代码来获取spring中配置的bean,并对该bean进行操作的情形.而最关键的一步就是获取ApplicationContext,过程中纠结和 ...

随机推荐

  1. BZOJ3874:[AHOI2014&JSOI2014]宅男计划(爬山法)

    Description  [故事背景] 自从迷上了拼图,JYY就变成了个彻底的宅男.为了解决温饱问题,JYY 不得不依靠叫外卖来维持生计. [问题描述] 外卖店一共有N种食物,分别有1到N编号.第i种 ...

  2. 【[ZJOI2010]网络扩容】

    题目 第一问直接板子敲上去 第二问并不明白直接在残量网络上加边的神仙做法 非常显然我们需要让流量加\(k\),那么我们就使得网络里的总流量为\(maxf+k\),\(maxf\)是第一问求出来的最大流 ...

  3. 【[NOI2013]矩阵游戏】

    我们看到了及其可怕的数据范围 这个样子都没有办法直接读入的数据范围应该怎么算 我们观察一下递推式\(f[i][j]=a*f[i][j]+b(j!=1)\) \(f[i][1]=c*f[i-1][m]+ ...

  4. Linux 进程状态标识 Process State Definition

    From : http://www.linfo.org/process_state.html 译者:李秋豪 进程状态标识是指在进程描述符中状态位的值. 进程,也可被称为任务,是指一个程序运行的实例. ...

  5. ActionBar 的应用

    转载:http://blog.csdn.net/yuxlong2010 作为Android 3.0之后引入的新的对象,ActionBar可以说是一个方便快捷的导航神器.它可以作为活动的标题,突出活动的 ...

  6. Win7安装MinGW

    MinGW官网:http://www.mingw.org/ 点击下载,稍后就会跳转到下载页面 下载文件后是一个在线安装包,下载过程有点长 Basic Setup里的包都需要安装,点击Installat ...

  7. VSTO Project 客户端自动发送邮件

    利用office vsto功能,抓取我们选择的任务,根据配置节,邮件发送内容,最终根据任务名称,任务开始结束时间,任务资源名称,发送邮件给任务资源. 这是我的VSTO界面. 配置我们发送邮件的服务器地 ...

  8. Vue nodejs商城项目-商品列表页面组件

    data(){        return {            goodsList:[], // 商品列表            priceFilter:[ // 价格区间数组          ...

  9. Java数据结构——二叉树 增加、删除、查询

    //二叉树系统 public class BinarySystem { public static void main(String[] args) { BinaryDomain root = nul ...

  10. Java基础——数组复习

    数组是一个变量,存储相同数据类型的一组数据 声明一个变量就是在内存空间划出一块合适的空间 声明一个数组就是在内存空间划出一串连续的空间 数组长度固定不变,避免数组越界   数组是静态分配内存空间的,所 ...