精华内容
下载资源
问答
  • Android 来电自动接听

    千次阅读 2017-10-10 15:20:52
    Android 来电自动接听、挂断。 今天闲来无事,刚好一个朋友需要做一个来电自动接听的功能,我一想,咦,这尼玛我还没做过,好吧,去看看!好吧,看就看吧那么我提来了,我该从哪儿入手呢?

    1、闲聊

            今天闲来无事,刚好一个朋友需要做一个来电自动接听的功能,我一想,咦,这尼玛我还没做过,好吧,去看看!好吧,看就看吧那么我提来了,我该从哪儿入手呢?算了还是走老步奏把,我想去看了看Andorid api 文档找到了一个东西:
    这里写图片描述

            这个包 提供用于监视基本电话信息的api,如网络类型和连接状态,以及操作电话号码字符串的实用程序。


    然后呢?我就在这里面找到了一个来电的监听器:
    这里写图片描述


    我以为到了这一步就好做了,然而我监听到了来电,却接听不了!What?怎么会这样?于是我就去逛一下博客,结果博客的来带你自动接听一团糟,思前想后,不是个办法啊,最总皇天不负有心人,我还是找到了一个关键的东西“aidl”!

    2、AIDL

            到了这里我们了解一下“aidl”是做啥的!AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言。AIDL这门语言非常的简单,基本上它的语法和 Java 是一样的,只是在一些细微处有些许差别——毕竟它只是被创造出来简化Android程序员工作的。对于小白来说,AIDL的作用是让你可以在自己的APP里绑定一个其他APP的service,这样你的APP可以和其他APP交互。当然它在我开发中最常用的还是写一些插件,如:Android ButterKnife Zelezny , Android Parcelable code generator , GsonFormat , Parcelable Code Generator(for kotlin)等。


    多说无用,现在我们像一个小白一样的去使用它就行了,以后深入了解!


    说到这儿,我就分享一个 Android系统aidl 的github地址:

    https://github.com/android/platform_frameworks_base

    3、找到被Android系统隐藏的方法

            那么我就需要,建立一个aidl的文件夹,并且与java文件夹同级!如图:

    这里写图片描述

    来吧,我们直接上这几个文件的源码,上源码之前必须说的一点是,包名必须与android系统框架下的包名相同!


    CellInfo.aidl
    
    package android.telephony;
    
    parcelable CellInfo;

    NeighboringCellInfo.aidl
    
    package android.telephony;
    
    parcelable NeighboringCellInfo;

    ITelephony.aidl
    
    package com.android.internal.telephony;
    
    interface ITelephony {
        boolean endCall();
        void answerRingingCall();
        boolean enableDataConnectivity();
        boolean disableDataConnectivity();
        boolean isDataConnectivityPossible();
    }

            到了这里我们编译一下就会发现:在编译文件中多了一个.class文件 : ( ITelephony ) ,如图位置:
    这里写图片描述


    ITelephony .class 源码如下:
    
    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package com.android.internal.telephony;
    
    import android.os.Binder;
    import android.os.IBinder;
    import android.os.IInterface;
    import android.os.Parcel;
    import android.os.RemoteException;
    
    public interface ITelephony extends IInterface {
        boolean endCall() throws RemoteException;
    
        void answerRingingCall() throws RemoteException;
    
        boolean enableDataConnectivity() throws RemoteException;
    
        boolean disableDataConnectivity() throws RemoteException;
    
        boolean isDataConnectivityPossible() throws RemoteException;
    
        public abstract static class Stub extends Binder implements ITelephony {
            private static final String DESCRIPTOR = "com.android.internal.telephony.ITelephony";
            static final int TRANSACTION_endCall = 1;
            static final int TRANSACTION_answerRingingCall = 2;
            static final int TRANSACTION_enableDataConnectivity = 3;
            static final int TRANSACTION_disableDataConnectivity = 4;
            static final int TRANSACTION_isDataConnectivityPossible = 5;
    
            public Stub() {
                this.attachInterface(this, "com.android.internal.telephony.ITelephony");
            }
    
            public static ITelephony asInterface(IBinder obj) {
                if(obj == null) {
                    return null;
                } else {
                    IInterface iin = obj.queryLocalInterface("com.android.internal.telephony.ITelephony");
                    return (ITelephony)(iin != null && iin instanceof ITelephony?(ITelephony)iin:new ITelephony.Stub.Proxy(obj));
                }
            }
    
            public IBinder asBinder() {
                return this;
            }
    
            public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
                boolean _result;
                switch(code) {
                case 1:
                    data.enforceInterface("com.android.internal.telephony.ITelephony");
                    _result = this.endCall();
                    reply.writeNoException();
                    reply.writeInt(_result?1:0);
                    return true;
                case 2:
                    data.enforceInterface("com.android.internal.telephony.ITelephony");
                    this.answerRingingCall();
                    reply.writeNoException();
                    return true;
                case 3:
                    data.enforceInterface("com.android.internal.telephony.ITelephony");
                    _result = this.enableDataConnectivity();
                    reply.writeNoException();
                    reply.writeInt(_result?1:0);
                    return true;
                case 4:
                    data.enforceInterface("com.android.internal.telephony.ITelephony");
                    _result = this.disableDataConnectivity();
                    reply.writeNoException();
                    reply.writeInt(_result?1:0);
                    return true;
                case 5:
                    data.enforceInterface("com.android.internal.telephony.ITelephony");
                    _result = this.isDataConnectivityPossible();
                    reply.writeNoException();
                    reply.writeInt(_result?1:0);
                    return true;
                case 1598968902:
                    reply.writeString("com.android.internal.telephony.ITelephony");
                    return true;
                default:
                    return super.onTransact(code, data, reply, flags);
                }
            }
    
            private static class Proxy implements ITelephony {
                private IBinder mRemote;
    
                Proxy(IBinder remote) {
                    this.mRemote = remote;
                }
    
                public IBinder asBinder() {
                    return this.mRemote;
                }
    
                public String getInterfaceDescriptor() {
                    return "com.android.internal.telephony.ITelephony";
                }
    
                public boolean endCall() throws RemoteException {
                    Parcel _data = Parcel.obtain();
                    Parcel _reply = Parcel.obtain();
    
                    boolean _result;
                    try {
                        _data.writeInterfaceToken("com.android.internal.telephony.ITelephony");
                        this.mRemote.transact(1, _data, _reply, 0);
                        _reply.readException();
                        _result = 0 != _reply.readInt();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
    
                    return _result;
                }
    
                public void answerRingingCall() throws RemoteException {
                    Parcel _data = Parcel.obtain();
                    Parcel _reply = Parcel.obtain();
    
                    try {
                        _data.writeInterfaceToken("com.android.internal.telephony.ITelephony");
                        this.mRemote.transact(2, _data, _reply, 0);
                        _reply.readException();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
    
                }
    
                public boolean enableDataConnectivity() throws RemoteException {
                    Parcel _data = Parcel.obtain();
                    Parcel _reply = Parcel.obtain();
    
                    boolean _result;
                    try {
                        _data.writeInterfaceToken("com.android.internal.telephony.ITelephony");
                        this.mRemote.transact(3, _data, _reply, 0);
                        _reply.readException();
                        _result = 0 != _reply.readInt();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
    
                    return _result;
                }
    
                public boolean disableDataConnectivity() throws RemoteException {
                    Parcel _data = Parcel.obtain();
                    Parcel _reply = Parcel.obtain();
    
                    boolean _result;
                    try {
                        _data.writeInterfaceToken("com.android.internal.telephony.ITelephony");
                        this.mRemote.transact(4, _data, _reply, 0);
                        _reply.readException();
                        _result = 0 != _reply.readInt();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
    
                    return _result;
                }
    
                public boolean isDataConnectivityPossible() throws RemoteException {
                    Parcel _data = Parcel.obtain();
                    Parcel _reply = Parcel.obtain();
    
                    boolean _result;
                    try {
                        _data.writeInterfaceToken("com.android.internal.telephony.ITelephony");
                        this.mRemote.transact(5, _data, _reply, 0);
                        _reply.readException();
                        _result = 0 != _reply.readInt();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
    
                    return _result;
                }
            }
        }
    }
    

    4、开始使用

            这里我就不过来多介绍了!我们通过反射使用这个class文件,不过再次之前,需要先注册权限:

    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.CALL_PRIVILEGED" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

    注册来电监听的源码: 
    
    TelephonyManager telephony = (TelephonyManager) getApplication()
            .getSystemService(Context.TELEPHONY_SERVICE);
    telephony.listen(new PhoneStateListener() {
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
                case TelephonyManager.CALL_STATE_RINGING:
                    Log.i(TAG, "onCallStateChanged: 来电:" + incomingNumber);
                    if (true) {
                        answerPhone();
                    } else {
                        endPhone();
                    }
                    break;
                case TelephonyManager.CALL_STATE_IDLE:
                    Log.i(TAG, "onCallStateChanged: 挂断:" + incomingNumber);
                    break;
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    Log.i(TAG, "onCallStateChanged: 通话:" + incomingNumber);
                    break;
            }
            super.onCallStateChanged(state, incomingNumber);
        }
    }, PhoneStateListener.LISTEN_CALL_STATE);

    自动挂断的代码:
    
    private void endPhone() {
        Method method = null;
        try {
            method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
            IBinder binder = (IBinder) method.invoke(null, new Object[]{"phone"});
            ITelephony telephony = ITelephony.Stub.asInterface(binder);
            telephony.endCall();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    自动接听的代码:
    
    private void answerPhone() {
        Method method = null;
        try {
            method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
            IBinder binder = (IBinder) method.invoke(null, new Object[]{"phone"});
            ITelephony telephony = ITelephony.Stub.asInterface(binder);
            telephony.answerRingingCall();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    到了这里我以为可以自动接听了:然而我开始测试了一下自动挂断,咦,可以咯,我兴冲冲的有去测试了一下,What?Fuck!无形报错,最为致命!



    报了一个没有注册”android.permission.MODIFY_PHONE_STATE”这个权限的错误,如图:
    这里写图片描述

    5、解决问题

            好吧,我又去博客咯!找到了一个最简单粗暴的方法:

    private void answerPhone() {
        Method method = null;
        try {
            method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
            IBinder binder = (IBinder) method.invoke(null, new Object[]{"phone"});
            ITelephony telephony = ITelephony.Stub.asInterface(binder);
            telephony.answerRingingCall();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (Exception e) {
            Log.e(TAG, "" + e, e);
            try {
                Runtime.getRuntime().exec("input keyevent " +
                        Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));
            } catch (IOException e2) {
                // Runtime.exec(String) had an I/O problem, try to fall back
                String enforcedPerm = "android.permission.CALL_PRIVILEGED";
                Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                        Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
                                KeyEvent.KEYCODE_HEADSETHOOK));
                Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                        Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
                                KeyEvent.KEYCODE_HEADSETHOOK));
                sendOrderedBroadcast(btnDown, enforcedPerm);
                sendOrderedBroadcast(btnUp, enforcedPerm);
            }
        }
    }

    6、测试

            本人亲测几个测试机,发现7.0一下的手机,都行自动接听,当然自动挂断好像没有限制所有手机都可以吧!


    最后贴一下整个自动接听、挂断的源码吧:
    
    public class IncomingListenerActivity extends AppCompatActivity {
        private static final String TAG = "IncomingListenerActivity";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_incoming_listener);
            initListener();
        }
    
        private void initListener() {
            TelephonyManager telephony = (TelephonyManager) getApplication()
                    .getSystemService(Context.TELEPHONY_SERVICE);
            telephony.listen(new PhoneStateListener() {
                @Override
                public void onCallStateChanged(int state, String incomingNumber) {
                    switch (state) {
                        case TelephonyManager.CALL_STATE_RINGING:
                            Log.i(TAG, "onCallStateChanged: 来电:" + incomingNumber);
                            if (true) {
                                answerPhone();
                            } else {
                                endPhone();
                            }
                            break;
                        case TelephonyManager.CALL_STATE_IDLE:
                            Log.i(TAG, "onCallStateChanged: 挂断:" + incomingNumber);
                            break;
                        case TelephonyManager.CALL_STATE_OFFHOOK:
                            Log.i(TAG, "onCallStateChanged: 通话:" + incomingNumber);
                            break;
                    }
                    super.onCallStateChanged(state, incomingNumber);
                }
            }, PhoneStateListener.LISTEN_CALL_STATE);
        }
    
        private void endPhone() {
            Method method = null;
            try {
                method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
                IBinder binder = (IBinder) method.invoke(null, new Object[]{"phone"});
                ITelephony telephony = ITelephony.Stub.asInterface(binder);
                telephony.endCall();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    
        private void answerPhone() {
            Method method = null;
            try {
                method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
                IBinder binder = (IBinder) method.invoke(null, new Object[]{"phone"});
                ITelephony telephony = ITelephony.Stub.asInterface(binder);
                telephony.answerRingingCall();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (RemoteException e) {
                e.printStackTrace();
            } catch (Exception e) {
                Log.e(TAG, "" + e, e);
                try {
                    Runtime.getRuntime().exec("input keyevent " +
                            Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));
                } catch (IOException e2) {
                    // Runtime.exec(String) had an I/O problem, try to fall back
                    String enforcedPerm = "android.permission.CALL_PRIVILEGED";
                    Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                            Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
                                    KeyEvent.KEYCODE_HEADSETHOOK));
                    Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                            Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
                                    KeyEvent.KEYCODE_HEADSETHOOK));
                    sendOrderedBroadcast(btnDown, enforcedPerm);
                    sendOrderedBroadcast(btnUp, enforcedPerm);
                }
            }
        }
    }

    7、源码地址

    https://github.com/fountaintao/CustomControl/blob/master/app/src/main/java/com/taoyong/customcontrol/IncomingListenerActivity.java

    展开全文
  • android 来电自动接听和自动挂断     注意:android2.3版本不支持下面的自动接听方法。(会抛异常:java.lang.SecurityException: Neither user xxxxx nor current process has android.permission.MODIFY_...

    android 来电自动接听和自动挂断

     

     

    注意:android2.3版本不支持下面的自动接听方法。(会抛异常:java.lang.SecurityException: Neither user xxxxx nor current process has android.permission.MODIFY_PHONE_STATE.)

     

     

    第一步:准备应用环境需要的系统包和aidl文件。

     

    (1)在应用中创建包:android.telephony

    将android系统框架下的\framework\telephony\java\android\telephony目录中的NeighboringCellInfo.aidl文件复制到上面创建的包(android.telephony )中;

    (2)在应用中创建包:com.android.internal.telephony

    将android系统框架下的\framework\telephony\java\com\android\internal\telephony目录中的ITelephony.aidl文件复制到上面创建的包(com.android.internal.telephony )中;

     

     

    第二步:创建一个获取ITelephony的方法

    PhoneUtils.java

    Java代码  收藏代码

    1. package com.zhouzijing.android.demo;  
    2.   
    3. import java.lang.reflect.Method;  
    4. import com.android.internal.telephony.ITelephony;  
    5. import android.telephony.TelephonyManager;  
    6.   
    7. public class PhoneUtils {  
    8.     /** 
    9.      * 根据传入的TelephonyManager来取得系统的ITelephony实例. 
    10.      * @param telephony 
    11.      * @return 系统的ITelephony实例 
    12.      * @throws Exception 
    13.      */  
    14.     public static ITelephony getITelephony(TelephonyManager telephony) throws Exception {   
    15.         Method getITelephonyMethod = telephony.getClass().getDeclaredMethod("getITelephony");   
    16.         getITelephonyMethod.setAccessible(true);//私有化函数也能使用   
    17.         return (ITelephony)getITelephonyMethod.invoke(telephony);   
    18.     }  
    19. }  

     

    第三步:创建电话广播拦截器

    MyPhoneBroadcastReceiver.java

    Java代码  收藏代码

    1. package com.zhouzijing.android.demo;  
    2.   
    3. import com.android.internal.telephony.ITelephony;  
    4. import android.content.BroadcastReceiver;  
    5. import android.content.Context;  
    6. import android.content.Intent;  
    7. import android.telephony.TelephonyManager;  
    8. import android.util.Log;  
    9.   
    10. public class MyPhoneBroadcastReceiver extends BroadcastReceiver {  
    11.   
    12.     private final static String TAG = MyPhone.TAG;  
    13.       
    14.     @Override  
    15.     public void onReceive(Context context, Intent intent) {  
    16.         String action = intent.getAction();  
    17.         Log.i(TAG, "[Broadcast]"+action);  
    18.           
    19.         //呼入电话  
    20.         if(action.equals(MyPhone.B_PHONE_STATE)){  
    21.             Log.i(TAG, "[Broadcast]PHONE_STATE");  
    22.             doReceivePhone(context,intent);  
    23.         }  
    24.     }  
    25.       
    26.     /** 
    27.      * 处理电话广播. 
    28.      * @param context 
    29.      * @param intent 
    30.      */  
    31.     public void doReceivePhone(Context context, Intent intent) {  
    32.         String phoneNumber = intent.getStringExtra(  
    33. TelephonyManager.EXTRA_INCOMING_NUMBER);  
    34.         TelephonyManager telephony = (TelephonyManager)context.getSystemService(  
    35. Context.TELEPHONY_SERVICE);  
    36.         int state = telephony.getCallState();  
    37.           
    38.         switch(state){  
    39.         case TelephonyManager.CALL_STATE_RINGING:  
    40.             Log.i(TAG, "[Broadcast]等待接电话="+phoneNumber);  
    41.             try {  
    42.                 ITelephony iTelephony = PhoneUtils.getITelephony(telephony);  
    43.                 iTelephony.answerRingingCall();//自动接通电话  
    44.                 //iTelephony.endCall();//自动挂断电话  
    45.             } catch (Exception e) {  
    46.                 Log.e(TAG, "[Broadcast]Exception="+e.getMessage(), e);  
    47.             }  
    48.             break;  
    49.         case TelephonyManager.CALL_STATE_IDLE:  
    50.             Log.i(TAG, "[Broadcast]电话挂断="+phoneNumber);  
    51.             break;  
    52.         case TelephonyManager.CALL_STATE_OFFHOOK:  
    53.             Log.i(TAG, "[Broadcast]通话中="+phoneNumber);  
    54.             break;  
    55.         }  
    56.     }  
    57.   
    58. }  

     

     

    第四部:注册电话广播拦截器

    MyPhone.java

    Java代码  收藏代码

    1. package com.zhouzijing.android.demo;  
    2.   
    3. import android.app.Activity;  
    4. import android.content.IntentFilter;  
    5. import android.os.Bundle;  
    6. import android.telephony.TelephonyManager;  
    7. import android.util.Log;  
    8. import android.view.View;  
    9.   
    10. public class MyPhone extends Activity {  
    11.     public final static String TAG = "MyPhone";  
    12.       
    13.     public final static String B_PHONE_STATE = TelephonyManager.ACTION_PHONE_STATE_CHANGED;  
    14.       
    15.     private MyPhoneBroadcastReceiver mBroadcastReceiver;  
    16.       
    17.     @Override  
    18.     public void onCreate(Bundle savedInstanceState) {  
    19.         super.onCreate(savedInstanceState);  
    20.         setContentView(R.layout.my_phone);  
    21.     }  
    22.       
    23.     //按钮1-注册广播  
    24.     public void registerThis(View v) {  
    25.         Log.i(TAG, "registerThis");  
    26.         mBroadcastReceiver = new MyPhoneBroadcastReceiver();  
    27.         IntentFilter intentFilter = new IntentFilter();  
    28.         intentFilter.addAction(B_PHONE_STATE);  
    29.         intentFilter.setPriority(Integer.MAX_VALUE);  
    30.         registerReceiver(mBroadcastReceiver, intentFilter);  
    31.     }  
    32.       
    33.     //按钮2-撤销广播  
    34.     public void unregisterThis(View v) {  
    35.         Log.i(TAG, "unregisterThis");  
    36.         unregisterReceiver(mBroadcastReceiver);  
    37.     }  
    38.       
    39. }  

     

    第5步:在AndroidManifest.xml配置权限

    Xml代码  收藏代码

    1. <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
    2. <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />  
    3. <uses-permission android:name="android.permission.CALL_PHONE"/>  

     

    其中:

    Java代码  收藏代码

    1. iTelephony.answerRingingCall();//自动接通电话  

     必须有权限 android.permission.MODIFY_PHONE_STATE

     

    Java代码  收藏代码

    1. iTelephony.endCall();//自动挂断电话  

     必须有权限 android.permission.CALL_PHONE

    展开全文
  • Android实现电话来电自动接听功能

    千次阅读 热门讨论 2018-10-22 17:14:20
    关于手机来电自动接听这个需求公司领导提了有一段时间了,直到最近才开始处理这个功能。拿到这个需求,先分析了一下,肯定是牵扯到硬件层和系统层面了,到网上查了资料之后,发现都是大同小异,你抄他他抄你的,尝试...

    目录

     

    前言

    一、效果展示

    二、实现分析

    三、具体业务调整

    四、总结


    前言

    关于手机来电自动接听这个需求公司领导提了有一段时间了,直到最近才开始处理这个功能。拿到这个需求,先分析了一下,肯定是牵扯到硬件层和系统层面了,到网上查了资料之后,发现都是大同小异,你抄他他抄你的,尝试了几种方案,适配性较差,最后找到了一篇文章,地址在这:https://blog.csdn.net/z82367825/article/details/78820559?utm_source=blogxgwz1,这篇文章的适配结果还是较为理想的,感谢这位小伙伴!

    一、效果展示

    1、中兴 ZTE BV0730 Android6.0系统

    2、小米 MI MAX3 Android8.1系统

    3、小米 MI8 Android8.1系统

    二、实现分析

    这个功能目前没找到Android7.0版本的手机,所以没有在7.x版本上测试过是否可行,网上有人说7.0的不行,后面如果有手机,测试结果我会及时更新到文章中。主要的实现思路和代码实现,都是参考的上面那篇文章,所以我这里就不在详细说了,有需要的直接点击链接查看即可:https://blog.csdn.net/z82367825/article/details/78820559?utm_source=blogxgwz1

    大致分析一下:网上有些通过aidl结合反射机制的方法在很多手机上都不适用了,所以作者更换了思路,对不同版本的系统单独进行适配。首先,Android API大于等于19的时候,通过对AudioManager模拟耳机按键事件,来实现自动接听,当Android API小于19的时候,dispatchMediaKeyEvent方法是不支持的,所以又通过Runtime.getRuntime().exec来执行底层Linux下的程序或脚本((bat),adb shell input keyevent “value” 一般用于模拟物理事件)。在Android8.0出来之后,由于Android系统的安全性提高了,无法随意地模拟耳机按键事件。但是Android8.0官方推出了API让我们可以实现自动接听,官方文档说明 https://developer.android.com/about/versions/oreo/android-8.0.html?hl=zh-cn ,Android8.0引入了新的权限ANSWER_PHONE_CALLS,我们可以通过调用TelecomManager#acceptRingingCall()直接实现接听。

    需要注意的是ANSWER_PHONE_CALLS这权限被声明为必须动态获取的权限,并且8.0以后的权限一组权限中的单一权限必须单独申请,不会出现一组中一个有全都有的情况了,所以作者又针对targetSDKVersion作了一层判断,如果targetSDKVersion小于23,转换思路通过通知栏去获取Telecom进程的MediaController去模拟耳机按键事件。这样就完成了自动接听的适配。所有的接听功能,都是在Activity运行时调用,所以作者还写了一个不可见的空白Activity,它的作用是让应用置于前台状态,确保以上的功能能够顺利调用,简单来说就是起到了保活的作用。

    三、具体业务调整

    在我的项目中还有一个需求时要求针对指定的某些来电号码进行自动接听,所以我对作者的代码作了一点改动,又进行了一层来电号码监听的处理,需要通过TelephonyManager对象去实现PhoneStateListener的一个回调监听,代码也很简单:

    package com.nari.yihui.helper;
    
    import android.app.Service;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.telephony.PhoneStateListener;
    import android.telephony.TelephonyManager;
    
    import com.nari.yihui.ui.activity.CallWorkActivity;
    import com.nari.yihui.utils.LogUtil;
    
    /**
     * @作者:纪安奇
     * @时间:2018/10/16 14:13
     * @描述:通过广播监听来电
     */
    
    @SuppressWarnings("ALL")
    public class CallReceiver extends BroadcastReceiver {
    
        private static int mState = -1;
    
        @Override
        public void onReceive(final Context context, Intent intent) {
            if (!intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
                TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
                telephonyManager.listen(new PhoneStateListener() {
                    @Override
                    public void onCallStateChanged(int state, String incomingNumber) {
                        LogUtil.e("---------------"+state + "------" + mState);
                        if (mState != state) {
                            mState = state;
                            switch (state) {
                                case TelephonyManager.CALL_STATE_RINGING: //来电
                                    if (incomingNumber.equals("022" + UserManager.getInstance().getUser().getObj().getUser().getSipid())) {
                                        LogUtil.e("监听接听电话---------" + incomingNumber);
                                        Intent workIntent = new Intent(context, CallWorkActivity.class);
                                        workIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                        context.startActivity(workIntent);
                                    }
                                    break;
                                case TelephonyManager.CALL_STATE_OFFHOOK:
                                    break;
                                case TelephonyManager.CALL_STATE_IDLE:
                                    break;
                            }
                        }
                        super.onCallStateChanged(state, incomingNumber);
                    }
                }, PhoneStateListener.LISTEN_CALL_STATE);
            }
        }
    }

    四、总结

    因为国内的安卓手机都是各大厂商自己进行的ROM的定制,加上并没有那么多的手机测试,所以可能实际使用中还会碰到问题,所以如果有朋友用了这个功能发现有问题的,麻烦告知机型和系统版本号,感谢!完整代码原文中也有,这里也再附上GitHub地址:https://github.com/82367825/CallHepler

    展开全文
  • Windows Mobile来电自动接听这个功能,我在实现的时候,没有找到相关的接口函数(估计微软也不会给我们这样的借口函数)。所以就找到了一个解决自动接听这个问题的办法,就是模拟手机按下接听键。这样就可以...

    Windows Mobile来电自动接听这个功能,我在实现的时候,没有找到相关的接口函数(估计微软也不会给我们这样的借口函数)。所以就找到了一个解决自动接听这个问题的办法,就是模拟手机按下接听键。这样就可以实现了来电自动接听这一功能。

    模拟按电话的接听键:

    keybd_event(VK_F3, 0, 0, 0);
    keybd_event(VK_F3, 0, KEYEVENTF_KEYUP, 0);

     

    当我们的程序在监听到有电话来的时候就调用上面这两个函数,这样就可以自动接听电话了,不过话又说回来,在使用上面两个函数之前,最好先::Sleep(180);180是最小的了,我测试过150,就不能接听电话了。

     

     

    展开全文
  • android 来电自动接听和自动挂断     注意:android2.3版本不支持下面的自动接听方法。(会抛异常:java.lang.SecurityException: Neither user xxxxx nor current process has android.permission.MO
  • 来电自动接听源码

    2014-11-21 13:19:20
    大家应该知道谷歌已经屏蔽了该权限,但是笔者还是通过
  • //来电自动接听 try { phoneNum = incomingNumber; flag = true ; if (mTelephony.isRinging()) { mTelephony.silenceRinger(); mTelephony.answerRingingCall(); } } catch (Exception e) ...
  • 个别电话,来了必须要接,但不想听到对方的声音,有什么好办法可以代码实现吗? http://topic.csdn.net/u/20120104/16/c24fcd08-e761-4f01-9919-605072039fa9.html
  • 今天其它项目组请教android2.3无法自动接听电话的问题,原因是调用answerRingingCall时系统提示没有权限 Neither user 10099 nor current process has android.permission.MODIFY_PHONE_STATE.   网上搜了...
  • 今天其它项目组请教android2.3无法自动接听电话的问题,原因是调用answerRingingCall时系统提示没有权限 Neither user 10099 nor current process has android.permission.MODIFY_PHONE_STATE. 网上搜了...
  • 利用服务做的自动接听或者自动拒接来电,有个界面,用户可自行决定使用或者停止该服务。
  • 自动接听或者挂断来电

    千次阅读 2017-05-28 10:19:46
    自动接听或者挂断来电 电话状态监听

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 202
精华内容 80
关键字:

来电自动接听