首页 > 代码库 > android项目 之 来电管家(5) ----- 添加监听服务

android项目 之 来电管家(5) ----- 添加监听服务

       上面四节,已经实现了界面设计,黑名单(白名单的添加与删除与黑名单同理,不再赘述),启用监听开关,定时拦截开关,及拦截模式选择等功能,下面就要实现来电管家最核心的功能,也就是拦截功能。

        主要思路

                1.  制定拦截模式,这里主要有两个,一个是黑名单模式,也就是只拦截在黑名单中的号码;另一个就是白名单模式,拦截除了白名单以外的号码。

                2.  根据用户自定义设置信息,制定正则表达式,判断拦截的标准。

                3.  使用对应的类实现挂断电话的功能。

       

       监听模块主要是利用service实现功能,为了实现电话挂断功能,这里需要调用远程的AIDL Service,大多数书上都介绍要将Android源代码中如下两个文件复制到项目的相应位置:

             com.android.internal.telephony包下的ITelephony.aidl

             android.telephony包下的NeighboringCellinfo.aidl

       但是下载源码需要翻墙,有点麻烦,其实做这些的目的就是为了在根目录下自动生成ITelephony.java源文件,因此没有源码也可以,具体做法如下:

            1)在项目的src目录下,新建package:com.android.internal.telephony

            2)   在刚新建的package下,新建一个名为ITelephony.aidl的文件。

            3)   将以下代码拷到刚新建的文件中。

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

           这样,ADT会在根目录下自动生成ITelephony.java源文件了。

          service的整个代码如下,里面也有解释:

          ListenService.java

package com.example.callmanager;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.text.SimpleDateFormat;import java.util.Date;import android.app.Activity;import android.app.Service;import android.content.Context;import android.content.Intent;import android.content.SharedPreferences;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.media.AudioManager;import android.net.Uri;import android.os.IBinder;import android.os.RemoteException;import android.provider.ContactsContract.PhoneLookup;import android.telephony.PhoneStateListener;import android.telephony.TelephonyManager;import android.widget.Toast;import com.android.internal.telephony.ITelephony;public class ListenService extends Service {	TelephonyManager tManager;	private SQLiteDatabase db;	private SharedPreferences spf;	private CustomPhoneCallListener callListener;			@Override	public void onCreate() {		// TODO Auto-generated method stub		super.onCreate();			    System.out.println("create");	}			@Override	public int onStartCommand(Intent intent, int flags, int startId) {		// TODO Auto-generated method stub		tManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);			    callListener = new CustomPhoneCallListener();		spf = this.getSharedPreferences("setting", Activity.MODE_PRIVATE);		tManager.listen(callListener, PhoneStateListener.LISTEN_CALL_STATE);		System.out.println("start");		return super.onStartCommand(intent, flags, startId);	}			@Override	public void onDestroy() {		// TODO Auto-generated method stub		super.onDestroy();		callListener = null;		tManager = null;		System.out.println("destory");		stopSelf();	}	@Override	public boolean onUnbind(Intent intent) {		// TODO Auto-generated method stub		return super.onUnbind(intent);			}		//创建或打开数据库    public void create_db(){    	//创建或打开数据库    	db = SQLiteDatabase.openOrCreateDatabase(ListenService.this.getFilesDir().toString()+"/list.db3", null);    	if(db == null){    		Toast.makeText(ListenService.this,"数据库创建不成功",Toast.LENGTH_LONG).show();    	}    	else{    		    		/*//创建另一个表,用于存放来电信息    		db.execSQL("create table if not exists callInfo(_id integer primary key autoincrement," +    				"name varchar(50)," +    				"number varchar(15),"+    				"callTimes varchar(20));");*/    	    	}	    }	   //插入     public void insert_callInfo(String name,String number,String time){    	Cursor cursor = db.rawQuery("select * from callInfo where callTimes = '"+time+"';",null);    	if(cursor.getCount() == 0){    		db.execSQL("insert into callInfo(name,number,callTimes) values('"+ name+ "','" + number +"','" + time + "');");    	}    	cursor.close();    	    }		 public class CustomPhoneCallListener extends PhoneStateListener{	    	@Override	    	public void onCallStateChanged(int state, String incomingNumber) {	    		super.onCallStateChanged(state, incomingNumber);	    			    			if(spf.getBoolean("isStartListen", false)){		    			//判断该电话是否在黑名单中	    				create_db();	    				boolean callEnd_flag = false;	    				String incomingName = null;	    				SimpleDateFormat   formatter   =   new   SimpleDateFormat   ("MM-dd HH:mm");  				        Date   curDate   =   new   Date(System.currentTimeMillis());//获取当前时间 				        String   strTime   =   formatter.format(curDate);	    				//如果启用白名单模式	    				if(spf.getBoolean("isWhiteList",false)){	    					System.out.println("whiteList");	    					callEnd_flag = !isInWhiteList(incomingNumber);	    						    					//根据号码找到联系人姓名	    					incomingName = getContactsNameByNumber(incomingNumber);	    						    				}	    				//如果是黑名单模式	    				else{	    					incomingName = isInBalckList(incomingNumber);	    					if(incomingName == null)	    						callEnd_flag = false;	    					else	    						callEnd_flag = true;	    				}	    					    				//如果启用时间段,则判断当前拨打电话时间是否在设定时间段中	    				if(spf.getBoolean("isTime", false)){	    					System.out.println("inTime");	    					callEnd_flag = callEnd_flag && isInterceptTime(strTime);	    				}		    					    					    			switch(state){		    			case TelephonyManager.CALL_STATE_IDLE:		    				break;		    			case TelephonyManager.CALL_STATE_OFFHOOK :		    				break;		    			//当电话呼入时		    			case TelephonyManager.CALL_STATE_RINGING :		    				toggleRingerMute(getApplicationContext());		    						    				if(callEnd_flag){		    							    			        		    					try {									Method method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);									//获取远程telephony_service的IBindler对象的代理									IBinder binder = (IBinder)method.invoke(null, new Object[]{TELEPHONY_SERVICE});									//将IBinder对象的代理转换为ITelephony对象 									ITelephony telephony = ITelephony.Stub.asInterface(binder);									//挂断电话 									telephony.endCall();		    					} catch (NoSuchMethodException e) {									// TODO Auto-generated catch block									e.printStackTrace();								} catch (ClassNotFoundException e) {									// TODO Auto-generated catch block									e.printStackTrace();								} catch (IllegalAccessException e) {									// TODO Auto-generated catch block									e.printStackTrace();								} catch (IllegalArgumentException e) {									// TODO Auto-generated catch block									e.printStackTrace();								} catch (InvocationTargetException e) {									// TODO Auto-generated catch block									e.printStackTrace();								} catch (RemoteException e) {									// TODO Auto-generated catch block									e.printStackTrace();								}		    							    					//将该号码插入来电信息数据库中		    					//获得当前的时间 		    					if(incomingName == null){		    						incomingName = "陌生号码";		    					}		    			        insert_callInfo(incomingName, incomingNumber, strTime);		    			        		    				}		    				System.out.println("bindListen");		    						    				break;		    			}		    		}	    			    		db.close();	    	}	    }          //通过电话号码查找联系人的姓名,如果查找到,则返回联系人的姓名,否则,返回null	 	 public String getContactsNameByNumber(String number){		 Cursor c = getContentResolver().query(Uri.withAppendedPath(	             PhoneLookup.CONTENT_FILTER_URI, number), new String[] {	             PhoneLookup._ID,	             PhoneLookup.NUMBER,	             PhoneLookup.DISPLAY_NAME,	             PhoneLookup.TYPE, PhoneLookup.LABEL }, null, null,   null );		 if(c.getCount() == 0){			 return null;		 } 		 else {	         c.moveToFirst();	         return c.getString(2); //获取姓名	         	     }		 	 }	 	 private static int previousMuteMode = -1;	 /**	  * 来电静音	  * 	  * @param context	  */	 private void toggleRingerMute(Context context)	 {	     AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);	     if (previousMuteMode == -1)	     {	         previousMuteMode = am.getRingerMode();	         am.setRingerMode(0);	     }	     am.setRingerMode(previousMuteMode);	     previousMuteMode = -1;	 } 	 	 	 	 	 	 //判断当前拨打时间 是否在拦截时间段里	 public boolean isInterceptTime(String time){		 //如果启用时间段 		 if(spf.getBoolean("isTime", false)){			 String startTime = spf.getString("startTime", "");			 String endTime = spf.getString("endTime", "");			//比较当前时间是否在拦截时间段内			if(time.compareTo(startTime) >= 0 && time.compareTo(endTime) <= 0){				 return true;		    }		 }		 return false;	 }	 	 	 	 //判断给定号码是否在白名单中 	 public boolean isInWhiteList(String phone){		 Cursor cursor = db.rawQuery("select * from whiteList where number='"+phone+"';", null);		 cursor.moveToFirst();		 //如果该号码在白名单中,则返回true		 if(cursor.getCount() > 0){			 cursor.close();			 return true;		 }		 return false;	 }	 	 	//判断给定号码是否在黑名单中 	public String isInBalckList(String phone){	    	Cursor cursor = db.rawQuery("select * from blackList where number='"+phone+"';", null);	    	String name = null;	    	cursor.moveToFirst();	    	if(cursor.getCount()>0)	    		name = cursor.getString(cursor.getColumnIndex("name"));	    	cursor.close();	    	return name;	}		@Override		public IBinder onBind(Intent intent) {			// TODO Auto-generated method stub			return null;		}			}

             代码很长,但核心的就是CustomPhoneCallListener这一部分,里面的主要思路就是通过读取用户的设置信息,判断是否拦截。

             这里同时也实现了,将拦截信息写入数据库,所以也就有了上述代码中的数据库的相关代码了。

             最后,重要的一点,就是,和Activity一样,service同样也需要进行注册,在AndroidManifest.xml里添加:

 		<service android:name="com.example.callmanager.ListenService"     				android:enabled="true" >     			<intent-filter>         				<action android:name="com.example.callmanager.ListenService" />     			 </intent-filter>  		</service> 

          当然,因为要监听来电状态,少不了读取通话记录和读取电话状态的权限,在AndroidManifest.xml里添加:

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


         这样,在该需要启用该监听服务时,就可以通过Intent来启动该服务,当启用该服务后,即使退出了Activity,也可以实现监听,因为service依然在后台运行,这就是service最基本的功能。

       

 

 

 

android项目 之 来电管家(5) ----- 添加监听服务