码迷,mamicode.com
首页 > 移动开发 > 详细

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

时间:2014-09-15 15:56:29      阅读:303      评论:0      收藏:0      [点我收藏+]

标签:来电拦截   service   

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

        主要思路

                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) ----- 添加监听服务

标签:来电拦截   service   

原文地址:http://blog.csdn.net/jesson20121020/article/details/39292977

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!