Android项目实战--手机卫士17--拦截黑名单以及响一声电话的处理

来源:互联网 发布:美国二战军工生产知乎 编辑:程序博客网 时间:2024/05/05 02:40


今天,我们就把那个黑名单的逻辑给完成一下,主要就是拦截黑名单以及响一声电话的处理,

其实这个逻辑也很简单的啦,拦截黑名单就是在我们监听来电的那个类里面加一个判断就可以的啦,从我们上一次的黑名单的数据库里面读取出来,然后判断一下,如果是黑名单,那就直接挂断电话啦,至于响一声电话,也是在那个类里面加一个判断,判断一下电话响了多久而已,如果只是一瞬间,那么就是响一声电话啦,然后我们也把它挂掉,所以其实早主要的就是持断电话啦,至于如果挂断电话,那就要用到Android里面的AIDL啦,如果有不懂AIDL的,可以去看看我们这篇文章AIDL的调用写挂断电话


好啦,我们先把我们挂断电话的AIDL文件拷贝过来,然后我们现在就直接写代码啦

com.xiaobin.security.service.AddressService

package com.xiaobin.security.service;import java.lang.reflect.Method;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.app.Service;import android.content.ContentResolver;import android.content.Context;import android.content.Intent;import android.content.SharedPreferences;import android.database.ContentObserver;import android.database.Cursor;import android.graphics.PixelFormat;import android.os.Handler;import android.os.IBinder;import android.provider.CallLog;import android.telephony.PhoneStateListener;import android.telephony.TelephonyManager;import android.view.Gravity;import android.view.View;import android.view.WindowManager;import android.widget.LinearLayout;import android.widget.TextView;import com.android.internal.telephony.ITelephony;import com.xiaobin.security.R;import com.xiaobin.security.dao.BlackNumberDao;import com.xiaobin.security.engine.NumberAddressService;import com.xiaobin.security.ui.NumberSecurityActivity;public class AddressService extends Service{private TelephonyManager telephonyManager;private MyPhoneListener listener;private WindowManager windowManager;private View view;private BlackNumberDao dao;private SharedPreferences sp;private long start;private long end;@Overridepublic IBinder onBind(Intent intent){return null;}@Overridepublic void onCreate(){super.onCreate();sp = getSharedPreferences("config", Context.MODE_PRIVATE);dao = new BlackNumberDao(this);windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);listener = new MyPhoneListener();telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);telephonyManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);}@Overridepublic void onDestroy(){super.onDestroy();//停止监听telephonyManager.listen(listener, PhoneStateListener.LISTEN_NONE);}//挂断电话private void endCall(){try{//通过反射拿到android.os.ServiceManager里面的getService这个方法的对象Method method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);//通过反射调用这个getService方法,然后拿到IBinder对象,然后就可以进行aidl啦IBinder iBinder = (IBinder) method.invoke(null, new Object[] {TELEPHONY_SERVICE});ITelephony telephony = ITelephony.Stub.asInterface(iBinder);telephony.endCall();}catch (Exception e){e.printStackTrace();}}//清除通话记录private void cleanCallLog(String incomingNumber){ContentResolver resolver = getContentResolver();Cursor cursor = resolver.query(CallLog.Calls.CONTENT_URI, null, " number = ? ", new String[] {incomingNumber}, null);if(cursor.moveToNext()){String id = cursor.getString(cursor.getColumnIndex("_id"));resolver.delete(CallLog.Calls.CONTENT_URI, " _id = ? ", new String[] {id});}}//显示归属地的窗体private void showLocation(String address){WindowManager.LayoutParams params = new WindowManager.LayoutParams();params.width = WindowManager.LayoutParams.WRAP_CONTENT;params.height = WindowManager.LayoutParams.WRAP_CONTENT;params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE //无法获取焦点| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE //无法点击| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;//保持屏幕亮params.format = PixelFormat.TRANSLUCENT;//设置成半透明的params.type = WindowManager.LayoutParams.TYPE_TOAST;params.setTitle("Toast");//主要是确定坐标系是从左上角开始的,不然呆会设置位置的时候有些麻烦params.gravity = Gravity.LEFT | Gravity.TOP;params.x = sp.getInt("lastX", 0);params.y = sp.getInt("lastY", 0);view = View.inflate(getApplicationContext(), R.layout.show_location, null);LinearLayout ll = (LinearLayout) view.findViewById(R.id.ll_location);int type = sp.getInt("background", 0);switch(type){case 0 : ll.setBackgroundResource(R.drawable.call_locate_white);break;case 1 : ll.setBackgroundResource(R.drawable.call_locate_orange);break;case 2 : ll.setBackgroundResource(R.drawable.call_locate_green);break;case 3 : ll.setBackgroundResource(R.drawable.call_locate_blue);break;case 4 : ll.setBackgroundResource(R.drawable.call_locate_gray);break;default : break;}TextView tv = (TextView) view.findViewById(R.id.tv_show_location);tv.setText("归属地: " + address);windowManager.addView(view, params);}private void showNotifycation(String number){//拿到Nofitication的管理者NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);//new一个Nofitication出来Notification notification = new Notification(R.drawable.notification, "发现响一声电话", System.currentTimeMillis());Context context = getApplicationContext();//设置成一点击就消失notification.flags = Notification.FLAG_AUTO_CANCEL;Intent notificationIntent = new Intent(context, NumberSecurityActivity.class);notificationIntent.putExtra("number", number);PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);notification.setLatestEventInfo(context, "响一声号码", number, pendingIntent);//激活NofiticationnotificationManager.notify(0, notification);}//========================================================================private class MyPhoneListener extends PhoneStateListener{@Overridepublic void onCallStateChanged(int state, String incomingNumber){super.onCallStateChanged(state, incomingNumber);switch(state){case TelephonyManager.CALL_STATE_IDLE : //空闲状态end = System.currentTimeMillis();if((end > start) && ((end - start) < 2000)){start = end = 0;showNotifycation(incomingNumber);}if(view != null){windowManager.removeView(view);//移除显示归属地的那个viewview = null;}break;case TelephonyManager.CALL_STATE_OFFHOOK : //接通电话if(view != null){windowManager.removeView(view);//移除显示归属地的那个viewview = null;}break;case TelephonyManager.CALL_STATE_RINGING : //铃响状态start = System.currentTimeMillis();if(dao.find(incomingNumber)){endCall();//注册一个内容观察者,如果内容发生了改变之后,就执行删除的操作getContentResolver().registerContentObserver(CallLog.Calls.CONTENT_URI, true, new MyObserver(new Handler(), incomingNumber));}String address = NumberAddressService.getAddress(incomingNumber);showLocation(address);break;default : break;}}}private class MyObserver extends ContentObserver{private String number;public MyObserver(Handler handler, String number){super(handler);this.number = number;}@Overridepublic void onChange(boolean selfChange){super.onChange(selfChange);cleanCallLog(number);getContentResolver().unregisterContentObserver(this);}}}

大家可以看到,其实这个逻辑是不复杂的,主要还是AIDL的应用啦,

我们在上面还可以看到,我写了一个Notification在上面,主要是通知用户有一个响一声的电话,让用户知道,

关于这个Notification,其实Android的API里面已经有很详细的说明的啦,如果还想深入了解一下的,可以去看看


里面说得很详细的,各位可以看看

大家可以看到,我们在上面,当用户点击那个Notification的时候,我们就会返回到号码黑名单的那个界面啦,

这时,我们就可以做一些操作啦,我们可以把这个响一声的号码记录下来,然后提示用户是不是把它添加到黑名单中

现在我们就要修改一下我们的com.xiaobin.security.ui.NumberSecurityActivity

同时,我们也会对Dialog抽出来,做成一个函数

com.xiaobin.security.ui.NumberSecurityActivity

package com.xiaobin.security.ui;import java.util.List;import android.app.Activity;import android.app.AlertDialog;import android.content.DialogInterface;import android.content.Intent;import android.os.Bundle;import android.text.InputType;import android.text.TextUtils;import android.view.ContextMenu;import android.view.ContextMenu.ContextMenuInfo;import android.view.MenuInflater;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.view.Window;import android.widget.AdapterView.AdapterContextMenuInfo;import android.widget.BaseAdapter;import android.widget.Button;import android.widget.EditText;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;import com.xiaobin.security.R;import com.xiaobin.security.dao.BlackNumberDao;public class NumberSecurityActivity extends Activity{private ListView lv_number;private Button bt_number_add;private BlackNumberDao dao;private List<String> numbers;private NumberAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.number_security);dao = new BlackNumberDao(this);numbers = dao.findAll();adapter = new NumberAdapter();lv_number = (ListView) findViewById(R.id.lv_number);lv_number.setAdapter(adapter);//给listview注册一个上下文菜单registerForContextMenu(lv_number);bt_number_add = (Button) findViewById(R.id.bt_number_add);bt_number_add.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v){addNumber(null);}});}@Overrideprotected void onResume(){super.onResume();Intent intent = getIntent();String number = intent.getStringExtra("number");if(number != null){addNumber(number);}}@Overridepublic void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo){super.onCreateContextMenu(menu, v, menuInfo);MenuInflater inflater = getMenuInflater();inflater.inflate(R.menu.number, menu);}@Overridepublic boolean onContextItemSelected(MenuItem item){//拿到点击的菜单的信息AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();switch(item.getItemId()){case R.id.update_number : String oldNumber = numbers.get((int) info.id);updateNumber(oldNumber);break;case R.id.delete_number : int id = (int) info.id;String number = numbers.get(id);dao.delete(number);numbers = dao.findAll();adapter.notifyDataSetChanged();break;default : break;}return super.onContextItemSelected(item);}private void addNumber(String number){AlertDialog.Builder builder = new AlertDialog.Builder(NumberSecurityActivity.this);builder.setTitle("添加黑名单");final EditText et_number = new EditText(NumberSecurityActivity.this);et_number.setInputType(InputType.TYPE_CLASS_PHONE);et_number.setHint("请输入黑名单号码");if(number != null){et_number.setText(number);}builder.setView(et_number);builder.setPositiveButton("添加", new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which){String number = et_number.getText().toString().trim();if(TextUtils.isEmpty(number)){Toast.makeText(NumberSecurityActivity.this, "添加号码不能为空", Toast.LENGTH_SHORT).show();}else{dao.add(number);numbers = dao.findAll();adapter.notifyDataSetChanged();}}});builder.setNegativeButton("取消", new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which){}});builder.create().show();}private void updateNumber(final String oldNumber){AlertDialog.Builder builder = new AlertDialog.Builder(NumberSecurityActivity.this);builder.setTitle("更新黑名单");final EditText et_number = new EditText(NumberSecurityActivity.this);et_number.setInputType(InputType.TYPE_CLASS_PHONE);et_number.setHint("请输入新的号码");builder.setView(et_number);builder.setPositiveButton("修改", new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which){String number = et_number.getText().toString().trim();if(TextUtils.isEmpty(number)){Toast.makeText(NumberSecurityActivity.this, "添加号码不能为空", Toast.LENGTH_SHORT).show();}else{dao.update(oldNumber, number);numbers = dao.findAll();adapter.notifyDataSetChanged();}}});builder.setNegativeButton("取消", new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which){}});builder.create().show();}//==================================================================private class NumberAdapter extends BaseAdapter{@Overridepublic int getCount(){return numbers.size();}@Overridepublic Object getItem(int position){return numbers.get(position);}@Overridepublic long getItemId(int position){return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent){if(convertView == null){View view = View.inflate(NumberSecurityActivity.this, R.layout.number_security_item, null);TextView tv_item = (TextView) view.findViewById(R.id.tv_number_item);tv_item.setText(numbers.get(position));return view;}else{TextView tv_item = (TextView) convertView.findViewById(R.id.tv_number_item);tv_item.setText(numbers.get(position));return convertView;}}}}

好啦,到这里,我们今天的内容就讲完了,下一次,我们就讲一下短信的备份


今天源码下载