android 自动接电话



android系统提供了电话相关的接口供调用,比如获取电话状态,获取手机服务等,也包括获取电话状态。因此可以根据电话状态的不同做不同操作。

本例主要分析一个来电自动接电话的代码,代码是由别人写的,拿来一起学习:

要想监听电话状态,一般的做法是写一个广播接收器监听电话状态的改变,配置文件如下:

[java] view plaincopyprint?

1. <receiver android:name=".AutoAnswerReceiver" android:enabled="true">  

2.     <intent-filter>  

3.         <action android:name="android.intent.action.PHONE_STATE" />  

4.     </intent-filter>  

5. </receiver>  

        <receiverandroid:name=".AutoAnswerReceiver"android:enabled="true">

          <intent-filter>

            <actionandroid:name="android.intent.action.PHONE_STATE" />

          </intent-filter>

        </receiver>

这个时候如果电话状态改变,比如来电等,就可以进入代码,代码如下:

[java] view plaincopyprint?

1. import android.content.BroadcastReceiver;  

2. import android.content.Context;  

3. import android.content.Intent;  

4. import android.content.SharedPreferences;  

5. import android.database.Cursor;  

6. import android.media.AudioManager;  

7. import android.net.Uri;  

8. import android.preference.PreferenceManager;  

9. import android.provider.ContactsContract.PhoneLookup;  

10.import android.telephony.TelephonyManager;  

11.  

12.public class AutoAnswerReceiver extends BroadcastReceiver {  

13.    @Override  

14.    public void onReceive(Context context, Intent intent) {  

15.  

16.        // Load preferences  

17.        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);  

18.  

19.        // Check phone state  

20.        String phone_state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);  

21.        String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);  

22.  

23.        if (phone_state.equals(TelephonyManager.EXTRA_STATE_RINGING) && prefs.getBoolean("enabled"false)) {  

24.            // Check for "second call" restriction  

25.            if (prefs.getBoolean("no_second_call"false)) {  

26.                AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);  

27.                if (am.getMode() == AudioManager.MODE_IN_CALL) {  

28.                    return;  

29.                }  

30.            }             

31.  

32.            // Check for contact restrictions  

33.            String which_contacts = prefs.getString("which_contacts""all");  

34.            if (!which_contacts.equals("all")) {  

35.                int is_starred = isStarred(context, number);  

36.                if (which_contacts.equals("contacts") && is_starred < 0) {  

37.                    return;  

38.                }  

39.                else if (which_contacts.equals("starred") && is_starred < 1) {  

40.                    return;  

41.                }  

42.            }  

43.  

44.            // Call a service, since this could take a few seconds  

45.            context.startService(new Intent(context, AutoAnswerIntentService.class));  

46.        }         

47.    }  

48.  

49.    // returns -1 if not in contact list, 0 if not starred, 1 if starred  

50.    private int isStarred(Context context, String number) {  

51.        int starred = -1;  

52.        Cursor c = context.getContentResolver().query(  

53.                Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number),  

54.                new String[] {PhoneLookup.STARRED},  

55.                nullnullnull);  

56.        if (c != null) {  

57.            if (c.moveToFirst()) {  

58.                starred = c.getInt(0);  

59.            }  

60.            c.close();  

61.        }  

62.        return starred;  

63.    }  

64.}  

importandroid.content.BroadcastReceiver;

importandroid.content.Context;

importandroid.content.Intent;

importandroid.content.SharedPreferences;

importandroid.database.Cursor;

importandroid.media.AudioManager;

importandroid.net.Uri;

importandroid.preference.PreferenceManager;

importandroid.provider.ContactsContract.PhoneLookup;

importandroid.telephony.TelephonyManager;

 

publicclass AutoAnswerReceiver extends BroadcastReceiver {

  @Override

  public void onReceive(Context context, Intentintent) {

 

    // Load preferences

    SharedPreferences prefs =PreferenceManager.getDefaultSharedPreferences(context);

 

    // Check phone state

    String phone_state =intent.getStringExtra(TelephonyManager.EXTRA_STATE);

    String number =intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);

 

    if(phone_state.equals(TelephonyManager.EXTRA_STATE_RINGING) &&prefs.getBoolean("enabled", false)) {

     // Check for "second call"restriction

     if (prefs.getBoolean("no_second_call",false)) {

       AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);

       if (am.getMode() ==AudioManager.MODE_IN_CALL) {

         return;

       }

     }    

 

     // Check for contact restrictions

     String which_contacts = prefs.getString("which_contacts","all");

     if(!which_contacts.equals("all")) {

       int is_starred = isStarred(context,number);

       if(which_contacts.equals("contacts") && is_starred < 0) {

         return;

       }

       else if(which_contacts.equals("starred") && is_starred < 1) {

         return;

       }

     }

 

     // Call a service, since this could take afew seconds

     context.startService(new Intent(context,AutoAnswerIntentService.class));

    }   

  }

 

  // returns -1 if not in contact list, 0 if notstarred, 1 if starred

  private int isStarred(Context context, Stringnumber) {

    int starred = -1;

    Cursor c =context.getContentResolver().query(

       Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,number),

       new String[] {PhoneLookup.STARRED},

       null, null, null);

    if (c != null) {

     if (c.moveToFirst()) {

       starred = c.getInt(0);

     }

     c.close();

    }

    return starred;

  }

}

暂且不管其他代码,因为其他的代码主要是对设置选项分别作判断,如果电话状态改变,则启动自动接听服务,即:context.startService(newIntent(context, AutoAnswerIntentService.class));

这样就启动了自动接听服务,在这个代码中,使用到了蓝牙接听电话的逻辑,也大概做一介绍:

先看代码如下:

[java] view plaincopyprint?

1. protected void onHandleIntent(Intent intent) {  

2.     Context context = getBaseContext();  

3.   

4.     // Load preferences  

5.     SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);  

6.     BluetoothHeadset bh = null;  

7.     if (prefs.getBoolean("headset_only"false)) {  

8.         bh = new BluetoothHeadset(thisnull);  

9.     }  

10.  

11.    // Let the phone ring for a set delay  

12.    try {  

13.        Thread.sleep(Integer.parseInt(prefs.getString("delay""2")) * 1000);  

14.    } catch (InterruptedException e) {  

15.        // We don't really care  

16.    }  

17.  

18.    // Check headset status right before picking up the call  

19.    if (prefs.getBoolean("headset_only"false) && bh != null) {  

20.        if (bh.getState() != BluetoothHeadset.STATE_CONNECTED) {  

21.            bh.close();  

22.            return;  

23.        }  

24.        bh.close();  

25.    }  

26.  

27.    // Make sure the phone is still ringing  

28.    TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);  

29.    if (tm.getCallState() != TelephonyManager.CALL_STATE_RINGING) {  

30.        return;  

31.    }  

32.  

33.    // Answer the phone  

34.    try {  

35.        answerPhoneAidl(context);  

36.    }  

37.    catch (Exception e) {  

38.        e.printStackTrace();  

39.        Log.d("AutoAnswer","Error trying to answer using telephony service.  Falling back to headset.");  

40.        answerPhoneHeadsethook(context);  

41.    }  

42.  

43.    // Enable the speakerphone  

44.    if (prefs.getBoolean("use_speakerphone"false)) {  

45.        enableSpeakerPhone(context);  

46.    }  

47.    return;  

48.}  

  protected void onHandleIntent(Intent intent) {

    Context context = getBaseContext();

 

    // Load preferences

    SharedPreferences prefs =PreferenceManager.getDefaultSharedPreferences(context);

    BluetoothHeadset bh = null;

    if(prefs.getBoolean("headset_only", false)) {

     bh = new BluetoothHeadset(this, null);

    }

 

    // Let the phone ring for a set delay

    try {

     Thread.sleep(Integer.parseInt(prefs.getString("delay","2")) * 1000);

    } catch (InterruptedException e) {

     // We don't really care

    }

 

    // Check headset status right before pickingup the call

    if(prefs.getBoolean("headset_only", false) && bh != null) {

     if (bh.getState() !=BluetoothHeadset.STATE_CONNECTED) {

       bh.close();

       return;

     }

     bh.close();

    }

 

    // Make sure the phone is still ringing

    TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);

    if (tm.getCallState() !=TelephonyManager.CALL_STATE_RINGING) {

     return;

    }

 

    // Answer the phone

    try {

     answerPhoneAidl(context);

    }

    catch (Exception e) {

     e.printStackTrace();

     Log.d("AutoAnswer","Errortrying to answer using telephony service. Falling back to headset.");

     answerPhoneHeadsethook(context);

    }

 

    // Enable the speakerphone

    if(prefs.getBoolean("use_speakerphone", false)) {

     enableSpeakerPhone(context);

    }

    return;

  }

先判断是否设置为蓝牙耳机接电话,如果不是则使用普通方式接听,当然先确保此时电话还在响铃,因为有时候电话也可能只响一声。然后就自动接电话,见answerPhoneAidl(context); ,其中接电话的这段代码如下:

[java] view plaincopyprint?

1. // Answer the phone  

2. try {  

3.     answerPhoneAidl(context);  

4. }  

5. catch (Exception e) {  

6.     e.printStackTrace();  

7.     Log.d("AutoAnswer","Error trying to answer using telephony service.  Falling back to headset.");  

8.     answerPhoneHeadsethook(context);  

9. }  

    // Answer the phone

    try {

     answerPhoneAidl(context);

    }

    catch (Exception e) {

     e.printStackTrace();

     Log.d("AutoAnswer","Errortrying to answer using telephony service. Falling back to headset.");

     answerPhoneHeadsethook(context);

    }

先使用一般的aidl方式接听电话,如果出现异常,则模拟一个按键来接听电话,两段代码见下:

[java] view plaincopyprint?

1. private void answerPhoneHeadsethook(Context context) {  

2.     // Simulate a press of the headset button to pick up the call  

3.     Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);       

4.     buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));  

5.     context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED");  

6.   

7.     // froyo and beyond trigger on buttonUp instead of buttonDown  

8.     Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);         

9.     buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));  

10.    context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");  

11.}  

12.  

13.@SuppressWarnings("unchecked")  

14.private void answerPhoneAidl(Context context) throws Exception {  

15.    // Set up communication with the telephony service (thanks to Tedd's Droid Tools!)  

16.    TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);  

17.    Class c = Class.forName(tm.getClass().getName());  

18.    Method m = c.getDeclaredMethod("getITelephony");  

19.    m.setAccessible(true);  

20.    ITelephony telephonyService;  

21.    telephonyService = (ITelephony)m.invoke(tm);  

22.  

23.    // Silence the ringer and answer the call!  

24.    telephonyService.silenceRinger();  

25.    telephonyService.answerRingingCall();  

26.}  

  private void answerPhoneHeadsethook(Contextcontext) {

    // Simulate a press of the headset button topick up the call

    Intent buttonDown = newIntent(Intent.ACTION_MEDIA_BUTTON);   

    buttonDown.putExtra(Intent.EXTRA_KEY_EVENT,new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));

    context.sendOrderedBroadcast(buttonDown,"android.permission.CALL_PRIVILEGED");

 

    // froyo and beyond trigger on buttonUpinstead of buttonDown

    Intent buttonUp = newIntent(Intent.ACTION_MEDIA_BUTTON);   

    buttonUp.putExtra(Intent.EXTRA_KEY_EVENT,new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));

    context.sendOrderedBroadcast(buttonUp,"android.permission.CALL_PRIVILEGED");

  }

 

  @SuppressWarnings("unchecked")

  private void answerPhoneAidl(Context context)throws Exception {

    // Set up communication with the telephonyservice (thanks to Tedd's Droid Tools!)

    TelephonyManager tm = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);

    Class c =Class.forName(tm.getClass().getName());

    Method m =c.getDeclaredMethod("getITelephony");

    m.setAccessible(true);

    ITelephony telephonyService;

    telephonyService = (ITelephony)m.invoke(tm);

 

    // Silence the ringer and answer the call!

    telephonyService.silenceRinger();

    telephonyService.answerRingingCall();

  }

一般由上述代码就可以接电话了,或许在某些手机上,如果本身更改了framework代码实现,可能会接不起来,需要另作修改。

本文开始提到的设置选项就是该应用启动界面,是用PreferenceActivity写的,见下:

public class AutoAnswerPreferenceActivity extendsPreferenceActivity implements OnSharedPreferenceChangeListener 

然后加载xml,用户可以设置很多选项参数。

运行界面见下:

https://img-my.csdn.net/uploads/201301/26/1359196614_9517.png

 

另外,本例中还有一个开机启动类,配置文件见下:

[java] view plaincopyprint?

1. <receiver android:name=".AutoAnswerBootReceiver" android:enabled="true">  

2.     <intent-filter>  

3.         <action android:name="android.intent.action.BOOT_COMPLETED" />  

4.     </intent-filter>  

5. </receiver>  

        <receiverandroid:name=".AutoAnswerBootReceiver"android:enabled="true">

          <intent-filter>

            <actionandroid:name="android.intent.action.BOOT_COMPLETED" />

          </intent-filter>

        </receiver>

可以设置notification提示用户

[java] view plaincopyprint?

1. public void onReceive(Context context, Intent intent) {  

2.     AutoAnswerNotifier notifier = new AutoAnswerNotifier(context);  

3.     notifier.updateNotification();  

4. }  

  public void onReceive(Context context, Intentintent) {

   AutoAnswerNotifier notifier = newAutoAnswerNotifier(context);

   notifier.updateNotification();

  }


AutoAnswerNotifier
主要方法就是可以设置提示或者取消提示:

[java] view plaincopyprint?

1. private void enableNotification() {  

2.     // Intent to call to turn off AutoAnswer  

3.     Intent notificationIntent = new Intent(mContext, AutoAnswerPreferenceActivity.class);  

4.     PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, notificationIntent, 0);  

5.       

6.     // Create the notification  

7.     Notification n = new Notification(R.drawable.stat_sys_autoanswer, null0);  

8.     n.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;  

9.     n.setLatestEventInfo(mContext, mContext.getString(R.string.notification_title), mContext.getString(R.string.notification_text), pendingIntent);  

10.    mNotificationManager.notify(NOTIFICATION_ID, n);  

11.}  

12.  

13.private void disableNotification() {  

14.    mNotificationManager.cancel(NOTIFICATION_ID);  

15.}     

  private void enableNotification() {

   // Intent to call to turn off AutoAnswer

   Intent notificationIntent = newIntent(mContext, AutoAnswerPreferenceActivity.class);

   PendingIntent pendingIntent =PendingIntent.getActivity(mContext, 0, notificationIntent, 0);

  

   // Create the notification

   Notification n = newNotification(R.drawable.stat_sys_autoanswer, null, 0);

   n.flags |= Notification.FLAG_ONGOING_EVENT |Notification.FLAG_NO_CLEAR;

   n.setLatestEventInfo(mContext,mContext.getString(R.string.notification_title),mContext.getString(R.string.notification_text), pendingIntent);

   mNotificationManager.notify(NOTIFICATION_ID,n);

  }

 

  private void disableNotification() {

   mNotificationManager.cancel(NOTIFICATION_ID);

  } 


最后,别忘记添加权限,因为操作电话等相关服务需要相关权限:

[java] view plaincopyprint?

1. <uses-permission android:name="android.permission.BLUETOOTH" />  

2. <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />  

3. <uses-permission android:name="android.permission.READ_PHONE_STATE" />  

4. <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />  

5. <uses-permission android:name="android.permission.READ_CONTACTS" />  

6. <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />  

  <uses-permissionandroid:name="android.permission.BLUETOOTH" />

  <uses-permissionandroid:name="android.permission.MODIFY_AUDIO_SETTINGS" />

  <uses-permissionandroid:name="android.permission.READ_PHONE_STATE" />

  <uses-permissionandroid:name="android.permission.MODIFY_PHONE_STATE" />

  <uses-permission android:name="android.permission.READ_CONTACTS"/>

  <uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED" />

本例代码会一并上传供下载学习,链接如下:
http://download.csdn.net/detail/bawang_cn/5031509


come from:http://blog.csdn.net/bawang_cn/article/details/8545043 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值