手机安全卫士04

时间:2022-03-10 19:00:07

1.号码归属地查询的UI

2.号码归属地查询的原理

1.查询数据库

3.号码归属地的查询实现

1、把数据库拷贝到assets目录并创建包com.itheima.mobilesafe.db.dao包创建该类

      file:///android_aset/address.db 这种无法访问

2.  在SplashActivit页面做从Assets目录拷贝到data/data/<包名>/files/address.db数据库的代码

/**
* //path 把address.db这个数据库拷贝到data/data/《包名》/files/address.db
*/
private void copyDB() {
//只要你拷贝了一次,我就不要你再拷贝了
try {
File file = new File(getFilesDir(), "address.db");
if(file.exists()&&file.length()>0){
//正常了,就不需要拷贝了
Log.i(TAG, "正常了,就不需要拷贝了");
}else{
InputStream is = getAssets().open("address.db");

FileOutputStream fos = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len = 0;
while((len = is.read(buffer))!= -1){
fos.write(buffer, 0, len);
}
is.close();
fos.close();
}


} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
3.操作数据库放在独立的包下

  使用正则表达式输入号码

public class NumberAddressQueryUtils {

private static String path = "data/data/com.itheima.mobilesafe/files/address.db";

/**
* 传一个号码进来,返回一归属地回去
*
* @param number
* @return
*/
public static String queryNumber(String number) {
String address = number;
// path 把address.db这个数据库拷贝到data/data/《包名》/files/address.db
SQLiteDatabase database = SQLiteDatabase.openDatabase(path, null,
SQLiteDatabase.OPEN_READONLY);
// 手机号码 13 14 15 16 18
// 手机号码的正则表达式判断\d需要加\转义
if (number.matches("^1[34568]\\d{9}$")) {
// 手机号码

Cursor cursor = database
.rawQuery(
"select location from data2 where id = (select outkey from data1 where id = ?)",
new String[] { number.substring(0, 7) });

while (cursor.moveToNext()) {

String location = cursor.getString(0);
address = location;
}
cursor.close();

} else {
// 其他的电话号码
switch (number.length()) {
case 3:
// 110
address = "匪警号码";
break;
case 4:
// 5554
address = "模拟器";
break;
case 5:
// 10086
address = "客服电话";
break;
case 7:
//
address = "本地号码";
break;

case 8:
address = "本地号码";
break;

default:
// /处理长途电话 10
if (number.length() > 10 && number.startsWith("0")) {
// 010-59790386
Cursor cursor = database.rawQuery(
"select location from data2 where area = ?",
new String[] { number.substring(1, 3) });

while (cursor.moveToNext()) {
String location = cursor.getString(0);
address = location.substring(0, location.length() - 2);
}
cursor.close();

// 0855-59790386
cursor = database.rawQuery(
"select location from data2 where area = ?",
new String[] { number.substring(1, 4) });
while (cursor.moveToNext()) {
String location = cursor.getString(0);
address = location.substring(0, location.length() - 2);

}
}

break;
}

}

return address;
}

}
 

4.号码归属地的查询效果优化

1.文本改变的监听  addTextChangedListener(new TextWatcher(){})
ed_phone.addTextChangedListener(new TextWatcher() {

/**
* 当文本发生变化的时候回调
*/
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(s!= null&&s.length()>=3){
//查询数据库,并且显示结果
String address = NumberAddressQueryUtils.queryNumber(s.toString());
result.setText(address);
}

}

/**
* 当文本发生变化之前回调
*/
@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.输入框抖动和振动效果

 ----------抖动----------1.在res/anim下创建两个xml文件   shake.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXDelta="0"
android:interpolator="@anim/cycle_7"
android:toXDelta="10" />

  cycle_7.xml
<?xml version="1.0" encoding="utf-8"?>
<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:cycles="7" />
2.使用
Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);
et.startAnimation(shake);

----------振动---------
1.振动权限
<uses-permission android:name="android.permission.VIBRATE"/>
2.代码
/**
* 系统提供的振动服务
*/
private Vibrator vibrator;

vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); //初始化
//当电话号码为空的时候,就去振动手机提醒用户
//vibrator.vibrate(2000); //振动毫秒数

long[] pattern = {200,200,300,300,1000,2000};//振动规律,动停动停
//-1不重复 0循环振动 1;
vibrator.vibrate(pattern, -1);

6.来电号码归属地的显示

1.创建后台监听来电服务2.权限
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> 
3.在功能清单中注册服务<service>4.监听电话状态----(在服务中监听)
private TelephonyManager tm;
private MyListenerPhone listenerPhone; //监听器,监听来电
private OutCallReceiver receiver; //接收去电广播

// 服务里面的内部类
//广播接收者的生命周期和服务一样
class OutCallReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
// 这就是我们拿到的播出去的电话号码
String phone = getResultData();
// 查询数据库
String address = NumberAddressQueryUtils.queryNumber(phone);

Toast.makeText(context, address, 1).show();
}

}

//监听器监听来电
private class MyListenerPhone extends PhoneStateListener {

@Override
public void onCallStateChanged(int state, String incomingNumber) {
// state:状态,incomingNumber:来电号码
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_RINGING: // 来电铃声响起
// 查询数据库的操作
String address = NumberAddressQueryUtils
.queryNumber(incomingNumber);

Toast.makeText(getApplicationContext(), address, 1).show();

break;

case TelephonyManager.CALL_STATE_IDLE://电话的空闲状态:挂电话、来电拒绝
//把这个View移除
if(view != null ){
wm.removeView(view);
}


break;

default:
break;
}
}

}


//使用
public void onCreat(){

tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);

// 监听来电
listenerPhone = new MyListenerPhone();
tm.listen(listenerPhone, PhoneStateListener.LISTEN_CALL_STATE);//监听电话状态


//用代码去注册广播接收者
receiver = new OutCallReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.NEW_OUTGOING_CALL");
registerReceiver(receiver, filter);
}

public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
// 取消监听来电
tm.listen(listenerPhone, PhoneStateListener.LISTEN_NONE);
listenerPhone = null;

//用代码取消注册广播接收者
unregisterReceiver(receiver);
receiver = null;
}



 

 10.自定义吐司

1.吐司的布局文件--(address_show.xml)
<?xml version="1.0" encoding="utf-8"?>
<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"
>

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/ic_menu_call" />

<TextView
android:textColor="#000000"
android:id="@+id/tv_address"
android:textSize="22sp"
android:text="号码归属地"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</LinearLayout>

2.自定义吐司
 
/**
* 窗体管理者
*/
private WindowManager wm;
private View view;
//实例化窗体
wm = (WindowManager) getSystemService(WINDOW_SERVICE);



/**
* 自定义土司
* @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);

//"半透明","活力橙","卫士蓝","金属灰","苹果绿"
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};
SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);
view.setBackgroundResource(ids[sp.getInt("which", 0)]); //设置背景
textview.setText(address);
//窗体的参数就设置好了
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;
wm.addView(view, params);

}





//使用
myToast(address);
//停用吐司
if(view!=null){
wm.remove(View)
}