手机安全卫士05

1.吐司跟随手势移动

1.权限
 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
2.接上一节
     private WindowManager.LayoutParams params;
	long[] mHits = new long[2];

	/**
	 * 自定义土司
	 * 
	 * @param address
	 */
	public void myToast(String address) {
		view = View.inflate(this, R.layout.address_show, null);
		TextView textview = (TextView) view.findViewById(R.id.tv_address);
		view.setOnClickListener(new OnClickListener() {           //点击事件为一组动作,少一个都不行,如果触摸事件返回true,拦截按下动作,则点                                                                          //    击无效
			@Override
			public void onClick(View v) {
				System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1);
				mHits[mHits.length - 1] = SystemClock.uptimeMillis();
				if (mHits[0] >= (SystemClock.uptimeMillis() - 500)) {
					// 双击居中了。。。
					params.x = wm.getDefaultDisplay().getWidth()/2-view.getWidth()/2;
					wm.updateViewLayout(view, params);
					Editor editor = sp.edit();
					editor.putInt("lastx", params.x);
					editor.commit();
				}
			}
		});

		// 给view对象设置一个触摸的监听器
		view.setOnTouchListener(new OnTouchListener() {
			// 定义手指的初始化位置
			int startX;
			int startY;

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:// 手指按下屏幕
					startX = (int) event.getRawX();
					startY = (int) event.getRawY();
					Log.i(TAG, "手指摸到控件");
					break;
				case MotionEvent.ACTION_MOVE:// 手指在屏幕上移动
					int newX = (int) event.getRawX();
					int newY = (int) event.getRawY();
					int dx = newX - startX;
					int dy = newY - startY;
					Log.i(TAG, "手指在控件上移动");
					params.x += dx;
					params.y += dy;
					// 考虑边界问题
					if (params.x < 0) {
						params.x = 0;
					}
					if (params.y < 0) {
						params.y = 0;
					}
					if (params.x > (wm.getDefaultDisplay().getWidth() - view
							.getWidth())) {
						params.x = (wm.getDefaultDisplay().getWidth() - view
								.getWidth());
					}
					if (params.y > (wm.getDefaultDisplay().getHeight() - view
							.getHeight())) {
						params.y = (wm.getDefaultDisplay().getHeight() - view
								.getHeight());
					}
					wm.updateViewLayout(view, params);       //更新布局
					// 重新初始化手指的开始结束位置。
					startX = (int) event.getRawX();
					startY = (int) event.getRawY();
					break;
				case MotionEvent.ACTION_UP:// 手指离开屏幕一瞬间
					// 记录控件距离屏幕左上角的坐标
					Log.i(TAG, "手指离开控件");
					Editor editor = sp.edit();
					editor.putInt("lastx", params.x);
					editor.putInt("lasty", params.y);
					editor.commit();
					break;
				}
				return false;// 事件处理完毕了。不要让父控件 父布局响应触摸事件了。
			}
		});

		// "半透明","活力橙","卫士蓝","金属灰","苹果绿"
		int[] ids = { R.drawable.call_locate_white,
				R.drawable.call_locate_orange, R.drawable.call_locate_blue,
				R.drawable.call_locate_gray, R.drawable.call_locate_green };
		sp = getSharedPreferences("config", MODE_PRIVATE);
		view.setBackgroundResource(ids[sp.getInt("which", 0)]);
		textview.setText(address);
		// 窗体的参数就设置好了
		params = new WindowManager.LayoutParams();

		params.height = WindowManager.LayoutParams.WRAP_CONTENT;
		params.width = WindowManager.LayoutParams.WRAP_CONTENT;
		// 与窗体左上角对其
		params.gravity = Gravity.TOP + Gravity.LEFT;                //所在位置为(0,0)
		// 指定窗体距离左边100 上边100个像素
		params.x = sp.getInt("lastx", 0);
		params.y = sp.getInt("lasty", 0);
		params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
				| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
		params.format = PixelFormat.TRANSLUCENT;
		// android系统里面具有电话优先级的一种窗体类型,记得添加权限。
		params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;              
		wm.addView(view, params);

	}


2.双击击中

1.双击事件
public class MainActivity extends Activity {
	long firstClickTime;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}
	public void click(View view){
		if(firstClickTime>0){
			long sencondClickTime = SystemClock.uptimeMillis();
			long dtime = sencondClickTime - firstClickTime;
			if(dtime<500){
				Toast.makeText(this, "双击了", 0).show();
			}else{
				firstClickTime = 0;
			}
			return;
		}
		firstClickTime = SystemClock.uptimeMillis();
		new Thread(){
			public void run() {
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				firstClickTime = 0;
			};
		}.start();
	}
}
2.双击优化
	private WindowManager.LayoutParams params;
	long[] mHits = new long[2];
        view.setOnClickListener(new OnClickListener() {           //点击事件为一组动作,少一个都不行,如果触摸事件返回true,拦截按下动作,则点                                                                          //    击无效
			@Override
			public void onClick(View v) {
				System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1);
				mHits[mHits.length - 1] = SystemClock.uptimeMillis();
				if (mHits[0] >= (SystemClock.uptimeMillis() - 500)) {
					// 双击居中了。。。
					params.x = wm.getDefaultDisplay().getWidth()/2-view.getWidth()/2;
					wm.updateViewLayout(view, params);
				}
			}
		});

3.桌面动画---------类似拖动加速---------:见例子代码

3.黑名单号码界面显示

1.创建数据库代码,新建一个独立的包,.db
public class BlackNumberDBOpenHelper extends SQLiteOpenHelper {

	/**
	 * 数据库创建的构造方法 数据库名称 blacknumber.db
	 * @param context
	 */
	public BlackNumberDBOpenHelper(Context context) {
		super(context, "blacknumber.db", null, 1);
	}
	//初始化数据库的表结构
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL("create table blacknumber (_id integer primary key autoincrement,number varchar(20),mode varchar(2))");
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

	}

}

2.数据库操作类放在一个独立的包中,.db.dao
/**
 * 黑名单数据库的增删改查业务类
 * @author Administrator
 *
 */
public class BlackNumberDao {
	private BlackNumberDBOpenHelper helper;
	/**
	 * 构造方法
	 * @param context 上下文
	 */
	public BlackNumberDao(Context context) {
		helper = new BlackNumberDBOpenHelper(context);
	}
	/**
	 * 查询黑名单号码是是否存在
	 * @param number
	 * @return
	 */
	public boolean find(String number){
		boolean result = false;
		SQLiteDatabase db = helper.getReadableDatabase();
		Cursor cursor = db.rawQuery("select * from blacknumber where number=?", new String[]{number});
		if(cursor.moveToNext()){
			result = true;
		}
		cursor.close();
		db.close();
		return result;
	}
	/**
	 * 查询黑名单号码的拦截模式
	 * @param number
	 * @return 返回号码的拦截模式,不是黑名单号码返回null
	 */
	public String findMode(String number){
		String result = null;
		SQLiteDatabase db = helper.getReadableDatabase();
		Cursor cursor = db.rawQuery("select mode from blacknumber where number=?", new String[]{number});
		if(cursor.moveToNext()){
			result = cursor.getString(0);
		}
		cursor.close();
		db.close();
		return result;
	}
	/**
	 * 查询全部黑名单号码
	 * @return
	 */
	public List<BlackNumberInfo> findAll(){
		List<BlackNumberInfo> result = new ArrayList<BlackNumberInfo>();
		SQLiteDatabase db = helper.getReadableDatabase();
		Cursor cursor = db.rawQuery("select number,mode from blacknumber order by _id desc", null);
		while(cursor.moveToNext()){
			BlackNumberInfo info = new BlackNumberInfo();
			String number = cursor.getString(0);
			String mode = cursor.getString(1);
			info.setMode(mode);
			info.setNumber(number);
			result.add(info);
		}
		cursor.close();
		db.close();
		return result;
	}
	
	
	/**
	 * 添加黑名单号码
	 * @param number 黑名单号码
	 * @param mode 拦截模式 1.电话拦截 2.短信拦截 3.全部拦截
	 */
	public void add(String number,String mode){
		SQLiteDatabase db = helper.getWritableDatabase();
		ContentValues values = new ContentValues();
		values.put("number", number);
		values.put("mode", mode);
		db.insert("blacknumber", null, values);
		db.close();
	}
	/**
	 * 修改黑名单号码的拦截模式
	 * @param number 要修改的黑名单号码
	 * @param newmode 新的拦截模式
	 */
	public void update(String number,String newmode){
		SQLiteDatabase db = helper.getWritableDatabase();
		ContentValues values = new ContentValues();
		values.put("mode", newmode);
		db.update("blacknumber", values, "number=?", new String[]{number});
		db.close();
	}
	/**
	 * 删除黑名单号码
	 * @param number 要删除的黑名单号码
	 */
	public void delete(String number){
		SQLiteDatabase db = helper.getWritableDatabase();
		db.delete("blacknumber",  "number=?", new String[]{number});
		db.close();
	}
}

3..业务bean:放在一个独立的包下,.domain------------------------------类似人物类等
/**
 * 黑名单号码的业务bean
 * @author Administrator
 *
 */
public class BlackNumberInfo {
	private String number;
	private String mode;
	public String getNumber() {
		return number;
	}
	public void setNumber(String number) {
		this.number = number;
	}
	public String getMode() {
		return mode;
	}
	public void setMode(String mode) {
		this.mode = mode;
	}
	@Override
	public String toString() {
		return "BlackNumberInfo [number=" + number + ", mode=" + mode + "]";
	}
	
}


4.android测试类,放在一个独立的包中,.test
(1)新建一个类继承AndroidTestCase
(2)在配置文件中配置相关信息
 
 
 <instrumentation
        
android:name="android.test.InstrumentationTestRunner"
        
android:targetPackage="com.itheima.mobilesafe" />
<application>
 <uses-library android:name="android.test.runner" />
<application/>
(3)单元测试
public class TestBlackNumberDB extends AndroidTestCase {
	public void testCreateDB() throws Exception {
		BlackNumberDBOpenHelper helper = new BlackNumberDBOpenHelper(
				getContext());
		helper.getWritableDatabase();
	}

	public void testAdd() throws Exception {
		BlackNumberDao dao = new BlackNumberDao(getContext());
		long basenumber = 13500000000l;
		Random random = new Random();
		for (int i = 0; i < 100; i++) {
			dao.add(String.valueOf(basenumber+i), String.valueOf(random.nextInt(3)+1));
		}
	}
	
	public void testFindAll() throws Exception{
		BlackNumberDao dao = new BlackNumberDao(getContext());
		List<BlackNumberInfo> infos = dao.findAll();
		for(BlackNumberInfo info:infos){
			System.out.println(info.toString());
		}
	}

	public void testDelete() throws Exception {
		BlackNumberDao dao = new BlackNumberDao(getContext());
		dao.delete("110");
	}

	public void testUpdate() throws Exception {
		BlackNumberDao dao = new BlackNumberDao(getContext());
		dao.update("110", "2");
	}

	public void testFind() throws Exception {
		BlackNumberDao dao = new BlackNumberDao(getContext());
		boolean result = dao.find("110");
		assertEquals(true, result);
	}
}


4.listview的优化

(1)复用View
(2)findViewById会遍历id,使用一个类记录下控件的内存地址
   代码:


	private class CallSmsSafeAdapter extends BaseAdapter{
		@Override
		public int getCount() {
			return infos.size();
		}
		//有多少个条目被显示,这个方法就会被调用多少次
		@Override
		public View getView(final int position, View convertView, ViewGroup parent) {
			View view;
			ViewHolder holder;
			//1.减少内存中view对象创建的个数
			if(convertView==null){
				Log.i(TAG,"创建新的view对象:"+position);
			//把一个布局文件转化成  view对象。
				view  = View.inflate(getApplicationContext(), R.layout.list_item_callsms, null);
				//2.减少子孩子查询的次数  内存中对象的地址。
				holder = new ViewHolder();
				holder.tv_number = (TextView) view.findViewById(R.id.tv_black_number);
				holder.tv_mode = (TextView) view.findViewById(R.id.tv_block_mode);
				holder.iv_delete = (ImageView) view.findViewById(R.id.iv_delete);
				//当孩子生出来的时候找到他们的引用,存放在记事本,放在父亲的口袋
				view.setTag(holder);
			}else{
				Log.i(TAG,"厨房有历史的view对象,复用历史缓存的view对象:"+position);
				view = convertView;
				holder = (ViewHolder) view.getTag();//5%
			}
			holder.tv_number.setText(infos.get(position).getNumber());
			String mode = infos.get(position).getMode();
			if("1".equals(mode)){
				holder.tv_mode.setText("电话拦截");
			}else if("2".equals(mode)){
				holder.tv_mode.setText("短信拦截");
			}else{
				holder.tv_mode.setText("全部拦截");
			}
		
			return view;
		}
		@Override
		public Object getItem(int position) {
			return null;
		}

		@Override
		public long getItemId(int position) {
			return 0;
		}
	}
	/**
	 * view对象的容器
	 *记录孩子的内存地址。
	 *相当于一个记事本
	 */
	static class ViewHolder{
		TextView tv_number;
		TextView tv_mode;
		ImageView iv_delete;
	}


5.添加删除黑名单号码

(1)添加,弹出对话框
a.  布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="300dip"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:background="#ffffff"
     >

    <TextView
        android:layout_width="300dip"
        android:layout_height="50dip"
        android:background="#66ff6600"
        android:gravity="center"
        android:text="请输入黑名单号码"
        android:textColor="#000000"
        android:textSize="22sp" />

    <EditText
        android:id="@+id/et_blacknumber"
        android:layout_width="280dip"
        android:layout_height="wrap_content"
        android:hint="请输入黑名单号码"
        android:inputType="phone" />

    <LinearLayout
        android:layout_width="300dip"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="horizontal" >

        <CheckBox
            android:id="@+id/cb_phone"
            android:textColor="#000000"
            android:layout_width="140dip"
            android:layout_height="wrap_content"
            android:text="电话拦截" />

        <CheckBox
            android:id="@+id/cb_sms"
            android:textColor="#000000"
            android:layout_width="140dip"
            android:layout_height="wrap_content"
            android:text="短信拦截" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="300dip"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="horizontal" >

        <Button
               android:background="@drawable/button_select"
            android:id="@+id/ok"
            android:layout_width="140dip"
            android:layout_height="wrap_content"
            android:text="确定" />

        <Button
               android:background="@drawable/button_select"
            android:id="@+id/cancel"
            android:layout_width="140dip"
            android:layout_height="wrap_content"
            android:text="取消" />
    </LinearLayout>

</LinearLayout>

b.使用
		AlertDialog.Builder builder = new Builder(this);
		final AlertDialog dialog = builder.create();
		View contentView = View.inflate(this, R.layout.dialog_add_blacknumber,
				null);
		dialog.setView(contentView, 0, 0, 0, 0);
		dialog.show();
                //dialog.dismiss();

(2)添加到数据库,并实时更新listview
				//数据被加到数据库
				dao.add(blacknumber, mode);
				//更新listview集合里面的内容。
				BlackNumberInfo info = new BlackNumberInfo();
				info.setMode(mode);
				info.setNumber(blacknumber);
				infos.add(0, info);
				//通知listview数据适配器数据更新了。
				adapter.notifyDataSetChanged();

a. 新添加的放在第一位
查找数据库是反序:   
select number,mode from blacknumber order by _id desc

(3)删除
a.状态选择器    -----按下改变状态
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
          android:drawable="@drawable/ic_delete_btn_focused" /> <!-- pressed -->
    <item android:state_focused="true"
          android:drawable="@drawable/ic_delete_btn_focused" /> <!-- focused -->
    <item android:state_hovered="true"
          android:drawable="@drawable/ic_delete_btn_focused" /> <!-- hovered -->
    <item android:drawable="@drawable/ic_delete_btn" /> <!-- default -->
</selector>
b.设置相应的图片
c.使用
android:src="@drawable/delete_selector"



d.删除

holder.iv_delete.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					AlertDialog.Builder builder = new Builder(CallSmsSafeActivity.this);
					builder.setTitle("警告");
					builder.setMessage("确定要删除这条记录么?");
					builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							//删除数据库的内容
							dao.delete(infos.get(position).getNumber());
							//更新界面。
							infos.remove(position);
							//通知listview数据适配器更新
							adapter.notifyDataSetChanged();
						}
					});
					builder.setNegativeButton("取消", null);
					builder.show();
				}
			});
 

6.短信拦截的原理

(1)如果在清单文件中配置,程序一旦加载广播接收者就无法关闭,但用代码创建广播接收者,可以关闭:在服务中创建广播接收者
public class CallSmsSafeService extends Service {
	public static final String TAG = "CallSmsSafeService";
	private InnerSmsReceiver receiver;
	private BlackNumberDao dao;
	private TelephonyManager tm;
	private MyListener listener;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	private class InnerSmsReceiver extends BroadcastReceiver{
		@Override
		public void onReceive(Context context, Intent intent) {
			Log.i(TAG,"内部广播接受者, 短信到来了");
			//检查发件人是否是黑名单号码,设置短信拦截全部拦截。
			Object[] objs = (Object[]) intent.getExtras().get("pdus");
			for(Object obj:objs){
				SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) obj);
				//得到短信发件人
				String sender = smsMessage.getOriginatingAddress();
				String result = dao.findMode(sender);
				if("2".equals(result)||"3".equals(result)){
					Log.i(TAG,"拦截短信");
					abortBroadcast();
				}
				//演示代码。
				String body = smsMessage.getMessageBody();
				if(body.contains("fapiao")){
					//你的头发票亮的很  语言分词技术。
					Log.i(TAG,"拦截发票短信");
					abortBroadcast();
				}
			}
		}
	}
	
	@Override
	public void onCreate() {
		dao = new BlackNumberDao(this);
		receiver = new InnerSmsReceiver();
		IntentFilter filter =  new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
		filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
		registerReceiver(receiver,filter);
		super.onCreate();
	}
	
	@Override
	public void onDestroy() {
		unregisterReceiver(receiver);
		receiver = null;
		super.onDestroy();
	}

}

(2)开启关闭服务
       //黑名单拦截设置
	private SettingItemView siv_callsms_safe;
	private Intent callSmsSafeIntent;
		
        siv_callsms_safe = (SettingItemView) findViewById(R.id.siv_callsms_safe);
		callSmsSafeIntent = new Intent(this, CallSmsSafeService.class);
		siv_callsms_safe.setOnClickListener(new OnClickListener() {

					@Override
					public void onClick(View v) {
						if (siv_callsms_safe.isChecked()) {
							// 变为非选中状态
							siv_callsms_safe.setChecked(false);
							stopService(callSmsSafeIntent);
						} else {
							// 选择状态
							siv_callsms_safe.setChecked(true);
							startService(callSmsSafeIntent);
						}

					}
				});

              //服务是否启动
   		boolean iscallSmsServiceRunning = ServiceUtils.isServiceRunning(
				SettingActivity.this,
				"com.itheima.mobilesafe.service.CallSmsSafeService");


7.电话拦截

(1)权限,callphone
(2)调用系统包,创建新包
------------------------------------------见手机卫士day05
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值