MobileSafeNotes Day05

##Day05##

#5.1查询号码归属地数据库操作# **

前边将手机防盗模块全部做完了,功能也全部都实现了,开始做新的模块,首先实现一个常用的实用功能,查询号码归属地

即根据号码查询号码的归属地(所在的地方),即拨打电话的时候,腾讯管家,360 金山卫士等都会弹出一个对话框提醒你
	例如:133 3333 3333   河北秦皇岛   02年  200万  北京收藏家  不用,养着

第一位是:1
第二位是:34578
第三位是:0-9

中国:前三位可以确定手机号码的运营商,比如:131联通,133电信,134移动
	 从第三位开始往后四位(4-7):可以确定号码的归属地,比如:陕西
	所以,号码的前7位就可以确定手机号码的归属地:比如:陕西移动

这个不是移动联通或者电信定的,是由好心网友搞的,将号码和归属地存放到数据库中,根据号码去查询归属,在淘宝10元就可买它的数据库,做app或者手机安全软件的时候,需要这个。
这个也是安卓开发的一个理念,工作当中遇到一些控件或者效果不会了,不要想着自己去写,去研究



select outkey from data1 where id=1300001
select location from data2 where id=496

select location from data2 where id=(select outkey from data1 where id=1300001)

#5.2拷贝数据库# ***

注意:
	不能直接打开assets目录下的数据库,必须将数据库拷贝手机目录中,通过打开手机目录中的数据库我们来实现查询数据库的操作,但是可以打开assets目录下存放的html文件
拷贝数据库
	/**
	 * 拷贝数据库
	 */
	private void copyDb() {
		File file = new File(getFilesDir(), "address.db");
		//5.判断file是否存在,存在不去拷贝
		if (!file.exists()) {
			//1.获取assets管理者
			AssetManager assets = getAssets();
			InputStream in = null;
			FileOutputStream out = null;
			try {
				//2.通过assets管理者打开数据库
				in = assets.open("address.db");
				//getCacheDir() : 获取缓存路径,getFilesDir():获取文件的路径
				out = new FileOutputStream(file);
				//3.读写操作
				//缓冲区
				byte[] b = new byte[1024];
				int len = -1;
				while((len = in.read(b)) != -1){
					out.write(b, 0, len);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}finally{//有没有异常都会执行
				//out.close();
				//in.close();
				//4.关流
				IOUtils.closeQuietly(out);
				IOUtils.closeQuietly(in);
			}
		}
	}

#5.3打开数据库,查询号码归属地# ***

/**
 * 打开数据库,根据号码查询号码归属地
 * @param num
 * @return
 */
public String queryAddress(String num,Context context){
	String location = "";
	File file = new File(context.getFilesDir(), "address.db");
	//1.打开数据库
	//path : 数据库的路径
	//factory : 游标工厂
	//flags : 权限标签
	//file.getAbsolutePath() : 获取绝对路径
	SQLiteDatabase database = SQLiteDatabase.openDatabase(file.getAbsolutePath(), null, SQLiteDatabase.OPEN_READONLY);
	//2.查询号码归属地,substring:包含头不包含尾  0-6
	Cursor cursor = database.rawQuery("select location from data2 where id=(select outkey from data1 where id=?)", new String[]{num.substring(0, 7)});
	//3.解析cursor
	if (cursor.moveToNext()) {
		location = cursor.getString(0);
	}
	return location;
}
单元测试

#5.4查询号码归属地界面# **

Eidetext属性:
<!-- ems : 设置输入框可输入内容的长度 
textCursorDrawable : 设置光标的颜色, @null:和输入文字的颜色一致
-->

1.创建高级界面
2.创建查询号码归属地界面
3.实现查询操作
	public void queryaddress(View v){
		//1.获取输入的内容
		String phone = et_address_queryphone.getText().toString().trim();
		//2.判断号码是否为空
		if (TextUtils.isEmpty(phone)) {
			Toast.makeText(getApplicationContext(), "请输入要查询的号码", 0).show();
			return;
		}
		//3.查询号码归属地
		AddressDao addressDao = new AddressDao();
		String queryAddress = addressDao.queryAddress(phone, getApplicationContext());
		//4.判断查询的归属地是否为空
		if (!TextUtils.isEmpty(queryAddress)) {
			tv_address_queryaddress.setText(queryAddress);
		}
}

#5.5电话号码查询逻辑处理# ***

正则表达式
	正则表达式 ^1[34578]\d{9}$
根据正则匹配
	if (num.matches("^1[34578]\\d{9}$")) {
其他位数号码处理
	else{
		switch (num.length()) {
		case 3://110 120  119
			location = "特殊电话";
			break;
		case 4://5556   5554
			location = "虚拟电话";
		   	break;
		case 5://10086 10010  10000   95588
			location = "客服电话";
			break;
		case 7://本地电话
		case 8://本地电话
			location = "本地电话";
			break;
		default://长途电话   010 1234567 10位    010 12345678  11位    0372 12345678  12位
			//startsWith : 是否以哪个字符开头
			if (num.length() >= 10 && num.startsWith("0")) {
				//长途电话
				//根据区号查询相应归属地,3位和4位
				//3位
				//截取区号
				String result = num.substring(1, 3);//010 -> 10
				//根据区号查看归属地
				Cursor cursor = database.rawQuery("select location from data2 where area=?", new String[]{result});
				//解析cursor
				if (cursor.moveToNext()) {
					location = cursor.getString(0);
					location = location.substring(0, location.length()-2);
					cursor.close();
				}else{
					//当查询三位查询不出来,直接查询四位
					//复用前面三位区号使用的变量,可以减少内存的使用
					result = num.substring(1, 4);
					cursor = database.rawQuery("select location from data2 where area=?", new String[]{result});
					if (cursor.moveToNext()) {
						location = cursor.getString(0);
						location = location.substring(0, location.length()-2);
						cursor.close();
					}
				}
			}
			break;
		}
	}

#5.6动态显示号码归属地的操作# ***

	//监听输入框输入状态变化的操作
	et_address_queryphone.addTextChangedListener(new TextWatcher() {
		//当输入内容改变完成的时候调用
		//s : String
		//start : 新文本从哪个位置开始输入
		//before : 旧文件的长度
		//count : 新文本替换旧文本的字符个数
		@Override
		public void onTextChanged(CharSequence s, int start, int before, int count) {
			//获取输入新内容
			String phone = s.toString();
			//查询号码归属地
			String queryAddress = addressDao.queryAddress(phone, getApplicationContext());
			if (!TextUtils.isEmpty(queryAddress)) {
				tv_address_queryaddress.setText(queryAddress);
			}
		}
		//输入之前调用
		@Override
		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) {
			// TODO Auto-generated method stub
			
		}
		//输入之后调用
		@Override
		public void afterTextChanged(Editable s) {
			// TODO Auto-generated method stub
			
		}
	});

#5.7抖动的效果# **

借鉴别人代码的方式
	1.根据布局文件中的字段,查找所在布局文件
	2.根据布局文件名称,找到调用的java文件
	3.找到相应代码,可以借鉴
1.拷贝代码
	Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);
		代码去实现动画插入器
		//shake.setInterpolator(new Interpolator() {

			//@Override
			//public float getInterpolation(float x) {
			//return 0;//根据x的值去获取y的值  y=x^2  y=x-k
			//}
		//});
	et_address_queryphone.startAnimation(shake);
2.拷贝shake.xml
	<!-- interpolator : 动画插入器 -->
	<translate xmlns:android="http://schemas.android.com/apk/res/android"
	    android:duration="1000"
	    android:fromXDelta="0"
	    android:interpolator="@anim/cycle_7"
	    android:toXDelta="10" />
3.拷贝cycle_7

#5.8振动的效果# **

	//获取振动的管理者
	Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
	//振动
	//vibrator.vibrate(Long.MAX_VALUE);//milliseconds:振动的持续时间,有些国产手机始终振动一次,小米
	//pattern:振动频率
	//repeat : 是否重复   -1不重复,非-1重复
	vibrator.vibrate(new long[]{50l,20l,50l,20l}, -1);

权限
	<uses-permission android:name="android.permission.VIBRATE"/>

#5.9来电显示号码归属地# ****

1.创建一个addressService,清单文件配置
2.通过TelephoneManager实现监听来电显示的操作
	@Override
	public void onCreate() {
		super.onCreate();
		addressDao = new AddressDao();
		//1.获取电话的管理者
		telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
		myPhoneStateListener = new MyPhoneStateListener();
		//2.监听电话的状态
		//events:监听的事件
		telephonyManager.listen(myPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
	}
	//3.创建一个监听
	private class MyPhoneStateListener extends PhoneStateListener{
		//state : 电话的状态
		//incomingNumber : 来电的号码
		@Override
		public void onCallStateChanged(int state, String incomingNumber) {
			super.onCallStateChanged(state, incomingNumber);
			//4.判断电话的状态
			switch (state) {
			case TelephonyManager.CALL_STATE_IDLE://空闲的状态
				break;
			case TelephonyManager.CALL_STATE_RINGING://响铃的状态
				//5.查询显示号码归属地
				String queryAddress = addressDao.queryAddress(incomingNumber, getApplicationContext());
				if (!TextUtils.isEmpty(queryAddress)) {
					Toast.makeText(getApplicationContext(), queryAddress, 0).show();
				}
				break;
			case TelephonyManager.CALL_STATE_OFFHOOK://通话的状态
				break;
			}
		}
	}
	@Override
	public void onDestroy() {
		super.onDestroy();
		//6.取消监听状态
		telephonyManager.listen(myPhoneStateListener, PhoneStateListener.LISTEN_NONE);//不去监听任何状态
	}

3.在spalshactivity中开启服务

#5.10自定义Toast# **

显示toast
	1.获取一个WindowManager
		windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
	2.创建一个textview
		textView = new TextView(getApplicationContext());
		textView.setText(queryAddress);
		textView.setTextSize(100);
		textView.setTextColor(Color.RED);
	3.设置toast的属性
		//设置toast的属性,LayoutParams就代表控件的属性,你的控件在那个父控件上显示,你就要获取那个父控件的LayoutParams,表示你这个控件符合父控件的属性规则
		 WindowManager.LayoutParams params = new WindowManager.LayoutParams();
		 params.height = WindowManager.LayoutParams.WRAP_CONTENT;//高度包裹内容
         params.width = 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;//控件的类型,显示窗体上的类型
	4.将textivew添加到window
		windowManager.addView(textView, params);//先把属性设置给textview,然后将textview添加到窗体上
隐藏toast
	/**
	 * 隐藏toast的操作
	 */
	public void hideToast(){
		//隐藏toast
		//判断windowManager和textview是否为空,如果为空就不去remove
		if (windowManager != null && textView != null) {
			windowManager.removeView(textView);
			//避免用户再次使用隐藏报出view不在window的异常,同时也是为下次显示toast做准备
			windowManager = null;
			textView = null;
		}
		
	}

#5.11服务的开启# ***

alt+shift+m : 将相应的代码抽取方法中
1.在设置中心中增加显示号码归属地的条目
2.给条目增加点击事件
	/**
	 * 显示号码归属地
	 */
	private void address() {
		sv_setting_address.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				Intent intent = new Intent(SettingActivity.this,AddressService.class);
				if (sv_setting_address.isChecked()) {
					//关闭服务
					stopService(intent);
					sv_setting_address.setChecked(false);
				}else{
					//打开服务
					startService(intent);
					sv_setting_address.setChecked(true);
				}
			}
		});
	}
3.回显操作,动态获取服务是否开启  ***
	a.创建一个工具类
		public class AddressUtils {
			/**
			 * 动态获取服务是否开启
			 * @param className
			 * @return
			 */
			public static boolean isRunningService(String className,Context context){
				//1.进程的管理者,活动的管理者
				ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
				//2.获取正在运行的服务
				List<RunningServiceInfo> runningServices = activityManager.getRunningServices(1000);//maxNum : 返回上限,最多返回多少个服务,10M  10000M   10G
				//3.遍历集合
				for (RunningServiceInfo runningServiceInfo : runningServices) {
					//4.获取服务的标示
					//ComponentName : 组件的标示
					ComponentName componentName = runningServiceInfo.service;
					//5.根据标示获取服务的全类名
					String className2 = componentName.getClassName();
					//6.判断我们获取的服务的全类名是否和我们传递过来的全类名相同,相同就是表示服务已经开启,不相同就表示服务没有开启
					if (className.equals(className2)) {
						return true;
					}
				}
				return false;
			}
		}
	b.在activity中调用
		/动态的获取服务是否开启
		if (AddressUtils.isRunningService("cn.itcast.mobilesafexian02.service.AddressService", this)) {
			sv_setting_address.setChecked(true);
		}else{
			sv_setting_address.setChecked(false);
		}

#5.12修改toast样式# **

1.创建布局文件
	<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:orientation="horizontal" 
	    android:gravity="center_vertical"
	    android:background="@drawable/call_locate_blue"
	    >
	    <ImageView 
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:src="@drawable/ic_launcher"
	        />
	    <TextView 
	        android:id="@+id/tv_toastcustom_address"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:text="北京电信"
	        android:textSize="18sp"
	        android:textColor="#000000"
	        />
</LinearLayout>
2.在显示toast的方法中将布局文件转化成view对象
	view = View.inflate(getApplicationContext(), R.layout.toast_custom, null);
3.进行各种修改
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值