Android应用开发实例篇(2)-----挂接电震动
一、概述
Android原生自带的电话软件是不支持挂接电震动设置的,但很多时候我们却需要这功能,要实现这功能有两种可行的办法,一是修改电话软件的代码,二是使用第三方软件,在这里我利用的是第二种方法。我们知道,Android提供给了开发者通过API直接监听到的三种电话状态:CALL_STATE_IDLE、CALL_STATE_OFFHOOK和CALL_STATE_RINGING,网上有很多文章对这三种状态进行了说明,但具体哪种STATE对应于实际中的哪个状态却很少提到,下面进行说明。
电话一开始所处的状态无非就两种:去电和来电。下面的图片是来电和去电的流程图。
来电和去电的流程非常相似,图中蓝色字体的英文字母就是对应于API里的三种状态,关键的状态是OFFHOOK,通过仔细观察流程可以知道,如果先有RINGING状态再有OFFHOOK状态的话就处于来电;如果先有OFFHOOK的话就处于去电,在程序里可以通过一个标志位区分它们。实现中是通过一个boolean变量,初始化为false,在检测到RINGING状态时将变量置为true,在IDLE状态将它置为false,最后通过用户的设置共同决定是否震动。或许有人埋怨为什么Android只提供三种状态,其实通过这三种状态再结合一些标志变量就可以检测到电话处于任何一种状态。如果Android什么功能都提供了,那程序员靠什么吃饭?呵呵,开玩笑的。关于开机自动启动怎么实现就不说了,网上有一大堆文章。利用SharedPreferences保存用户的设置。
二、功能
1、支持挂、接电震动设置(还没实现主叫接通震动)
2、开机自动运行
三、实现
本程序主要由4个java源文件组成,VibrationMainActivity.java、PhoneReceiver.java、VibrationService.java和BootReceiver.java。
VibrationMainActivity.java提供界面给用户设置;PhoneReceiver.java监听接收电话状态改变并根据设置决定是否震动;VibrationService.java后台服务,负责注册和注销电话状态改变接收者(PhoneReceiver);BootReceiver.java监听开机信息并启动服务。
代码都很简单,直接上代码,最后注意一下权限。
VibrationMainActivity.java文件:
1 package com.nan.vibration; 2 3 import android.os.Bundle; 4 import android.app.Activity; 5 import android.content.Intent; 6 import android.content.SharedPreferences; 7 import android.view.Menu; 8 import android.widget.CheckBox; 9 import android.widget.CompoundButton; 10 11 12 13 public class VibrationMainActivity extends Activity 14 { 15 16 private CheckBox handOnCheckBox = null; 17 private CheckBox handUpCheckBox = null; 18 final Intent mIntent = new Intent(); 19 20 private SharedPreferences mSharedPreferences = null; 21 private SharedPreferences.Editor mEditor = null; 22 23 //记录用户设置(接通和挂断) 24 boolean handon = false; 25 boolean handup = false; 26 27 28 @Override 29 public void onCreate(Bundle savedInstanceState) 30 { 31 super.onCreate(savedInstanceState); 32 setContentView(R.layout.activity_vibration_main); 33 34 35 handOnCheckBox = (CheckBox)findViewById(R.id.hand_on_checkBox); 36 handUpCheckBox = (CheckBox)findViewById(R.id.hand_up_checkBox); 37 38 //获取用户设置 39 mSharedPreferences = getSharedPreferences("myshare",MODE_PRIVATE); 40 mEditor = mSharedPreferences.edit(); 41 42 //根据设置更新界面 43 handon = mSharedPreferences.getBoolean("On", false); 44 if(handon) 45 handOnCheckBox.setChecked(true); 46 else 47 handOnCheckBox.setChecked(false); 48 49 handup = mSharedPreferences.getBoolean("Up", false); 50 if(handup) 51 handUpCheckBox.setChecked(true); 52 else 53 handUpCheckBox.setChecked(false); 54 55 //用户启动service的动作 56 mIntent.setAction("com.nan.vibration.TELE_SERVICE"); 57 58 59 handOnCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 60 { 61 62 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 63 { 64 // TODO Auto-generated method stub 65 //用户设置改变时先停止service 66 stopService(mIntent); 67 68 if(isChecked) 69 handon = true; 70 else 71 handon = false; 72 //保存记录 73 mEditor.putBoolean("On", handon); 74 mEditor.commit(); 75 76 //用户设置完再开启service 77 startService(mIntent); 78 //如果两个都没有设置就停止service 79 if((!handup)&&(!handon)) 80 stopService(mIntent); 81 82 } 83 }); 84 85 handUpCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 86 { 87 88 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 89 { 90 // TODO Auto-generated method stub 91 //用户设置改变时先停止service 92 stopService(mIntent); 93 94 if(isChecked) 95 handup = true; 96 else 97 handup = false; 98 //保存记录 99 mEditor.putBoolean("Up", handup); 100 mEditor.commit(); 101 //用户设置完再开启service 102 startService(mIntent); 103 //如果两个都没有设置就停止service 104 if((!handon)&&(!handup)) 105 stopService(mIntent); 106 107 } 108 }); 109 110 111 } 112 113 114 @Override 115 public boolean onCreateOptionsMenu(Menu menu) { 116 getMenuInflater().inflate(R.menu.activity_vibration_main, menu); 117 return true; 118 } 119 }
VibrationService.java文件:
1 package com.nan.vibration; 2 3 import android.app.Service; 4 import android.content.Intent; 5 import android.content.IntentFilter; 6 import android.os.IBinder; 7 import android.telephony.TelephonyManager; 8 9 10 public class VibrationService extends Service 11 { 12 13 public final static String PHONE_STATE = TelephonyManager.ACTION_PHONE_STATE_CHANGED; 14 private PhoneReceiver mPhoneReceiver; 15 16 17 @Override 18 public IBinder onBind(Intent arg0) 19 { 20 // TODO Auto-generated method stub 21 22 return null; 23 } 24 25 @Override 26 public void onCreate() 27 { 28 29 } 30 31 @Override 32 public int onStartCommand(Intent intent, int flags, int startId) 33 { 34 mPhoneReceiver = new PhoneReceiver(); 35 IntentFilter intentFilter = new IntentFilter(); 36 //添加receiver接收的动作 37 intentFilter.addAction(PHONE_STATE); 38 intentFilter.setPriority(Integer.MAX_VALUE); 39 //注册receiver 40 registerReceiver(mPhoneReceiver, intentFilter); 41 42 return START_STICKY; 43 } 44 45 @Override 46 public void onDestroy() 47 { 48 //注销receiver 49 unregisterReceiver(mPhoneReceiver); 50 } 51 52 }
PhoneReceiver.java文件
1 package com.nan.vibration; 2 3 import android.app.Service; 4 import android.content.BroadcastReceiver; 5 import android.content.Context; 6 import android.content.Intent; 7 import android.content.SharedPreferences; 8 import android.os.Vibrator; 9 import android.telephony.TelephonyManager; 10 11 12 public class PhoneReceiver extends BroadcastReceiver 13 { 14 private Vibrator mVibrator = null; 15 private SharedPreferences mSharedPreferences = null; 16 boolean handon; 17 boolean handup; 18 boolean hadRinging = false; 19 20 @Override 21 public void onReceive(Context arg0, Intent arg1) 22 { 23 // TODO Auto-generated method stub 24 25 TelephonyManager tManager = (TelephonyManager) arg0.getSystemService(Service.TELEPHONY_SERVICE); 26 mVibrator = (Vibrator)arg0.getSystemService(Service.VIBRATOR_SERVICE); 27 mSharedPreferences = arg0.getSharedPreferences("myshare",0); 28 //读取用户设置 29 handon = mSharedPreferences.getBoolean("On", false); 30 handup = mSharedPreferences.getBoolean("Up", false); 31 32 switch(tManager.getCallState()) 33 { 34 //挂断 35 case TelephonyManager.CALL_STATE_IDLE: 36 { 37 if(handup) 38 mVibrator.vibrate(200);//震动200ms 39 hadRinging = false; 40 } 41 break; 42 //接通 43 case TelephonyManager.CALL_STATE_OFFHOOK: 44 { 45 if(handon&&hadRinging) 46 mVibrator.vibrate(200);//震动200ms 47 } 48 break; 49 //来电响铃 50 case TelephonyManager.CALL_STATE_RINGING: 51 { 52 hadRinging = true; 53 } 54 break; 55 // 56 default: 57 break; 58 } 59 60 61 } 62 63 }
BootReceiver.java文件
1 package com.nan.vibration; 2 3 import android.content.BroadcastReceiver; 4 import android.content.Context; 5 import android.content.Intent; 6 7 8 public class BootReceiver extends BroadcastReceiver 9 { 10 11 final Intent mIntent = new Intent(); 12 13 @Override 14 public void onReceive(Context arg0, Intent arg1) 15 { 16 // TODO Auto-generated method stub 17 //开机动作? 18 if(arg1.getAction().equals( Intent.ACTION_BOOT_COMPLETED )) 19 { 20 mIntent.setAction("com.nan.vibration.TELE_SERVICE"); 21 //开启service 22 arg0.startService(mIntent); 23 24 } 25 26 } 27 28 }
最后,AndroidManifest.xml文件
1 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 2 package="com.nan.vibration" 3 android:versionCode="1" 4 android:versionName="1.0" > 5 6 <uses-sdk 7 android:minSdkVersion="8" 8 android:targetSdkVersion="15" /> 9 10 <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 11 <uses-permission android:name="android.permission.VIBRATE" /> 12 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 13 14 15 <application 16 android:icon="@drawable/ic_launcher" 17 android:label="@string/app_name" 18 android:theme="@style/AppTheme" > 19 <activity 20 android:name=".VibrationMainActivity" 21 android:label="@string/title_activity_vibration_main" > 22 <intent-filter> 23 <action android:name="android.intent.action.MAIN" /> 24 25 <category android:name="android.intent.category.LAUNCHER" /> 26 </intent-filter> 27 </activity> 28 29 <service android:name=".VibrationService" android:exported="false" > 30 <intent-filter> 31 <action android:name="com.nan.vibration.TELE_SERVICE" /> 32 </intent-filter> 33 </service> 34 <receiver android:name=".BootReceiver"> 35 <intent-filter> 36 <action android:name="android.intent.action.BOOT_COMPLETED" /> 37 </intent-filter> 38 </receiver> 39 40 41 </application> 42 43 44 </manifest>
真机运行时:
PS:
本人在原生Android4.1.2的galaxy nexus(三星I9250)上亲测可用。