黑马程序员Android学习笔记——金山卫士项目——第四天
来源:互联网 发布:ww聊天软件下载 编辑:程序博客网 时间:2024/05/02 13:34
主要学习内容:
1)号码归属地查询UI设计
2)号码归属地查询的原理
3)号码归属地查询的代码实现
5)输入框抖动和震动效果
6)来电、去电号码归属地的显示
7)代码注册广播接受者的实现
8)自定义吐司显示号码归属地【实现号码归属地显示效果:加背景、加图片、加文字
首先看一下UI实现的效果:
通过UI效果可以清楚看到我们实现了哪些内容:第一幅图片的查询是查询过程中就在查数据库,动态加载电话号码信息;设置号码归属地是可选的;来电归属地显示效果通过自定义吐司实现不同效果。
查询原理:
第一种:联网查询;
第二种:把数据库 放在本地;
------1、百度上输入:手机号码归属地
-----2、数据库的来源,可以在淘宝上购买;
买的数据不一定是Android下用的数据库;
如果在Android上使用得自己做一个;把数据写到Android的数据库里;
号码归属地的查询实现
1、把数据库拷贝到assets目录并创建包com.itheima.mobilesafe.db.dao 包创建该类
file:///android_aset/address.db 这种无法访问
知识回顾:
WebView还可以加载图片String str = "file:///android_asset/icon.png";
在APP刚启动的时候,自动加载数据,将assets中的数据库复制到数据库。
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(is.read(buffer)!=-1){fos.write(buffer,0,len);}is.close();fos.close();} }catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
关于电话号码的常识可以到百度百科中搜集资料,非常多的介绍。
关于数据库查询归属地的工具代码如下:
package com.example.mobilesafe.db.dao;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;public class NumberAddressQueryUtils {private static String path="data/data/com.example.mobilesafe/files/address.db"; /* * 产一个号码进来,返回一个归属地回去 */public static String queryNumber(String number){String address=number;//path 把address.db这个数据库拷贝到data/data/包名/files/address.dbSQLiteDatabase database=SQLiteDatabase.openDatabase(path, null,SQLiteDatabase.OPEN_READONLY);//手机号码 13 14 15 16 18//手机号码正则表达式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)});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; System.out.println("address"+address);}cursor.close();}else{//其它的电话号码switch(number.length()){case 3:address="匪警号码";break;case 4:address="模拟器";break;//10086case 5:address="客服电话";break;case 7:address="本地号码";break;case 8:address="本地号码";break;default://处理长途电话if(number.length()>10&&number.startsWith("0")){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-353253445 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;}}
实现输入框输入部分位数号码只能查找该号码归属地:输入框是有状态事件的
private EditText ed_phone;
ed_phone.addTextChangedListener(new TextWatcher() {/* * 文本發生變化的時候回調 */@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {// TODO Auto-generated method stubif(s.length()>=3){//查詢數據庫String address=NumberAddressQueryUtils.queryNumber(s.toString());result.setText(address);}}/* * 文本發生變化之前變化(non-Javadoc) * @see android.text.TextWatcher#beforeTextChanged(java.lang.CharSequence, int, int, int) */@Overridepublic void beforeTextChanged(CharSequence s, int start, int count,int after) {// TODO Auto-generated method stub}/* * 文本發生變化之後回調(non-Javadoc) * @see android.text.TextWatcher#afterTextChanged(android.text.Editable) */@Overridepublic void afterTextChanged(Editable s) {// TODO Auto-generated method stub}});
输入框或者其它组件震动与抖动效果实现
抖动和振动效果_32
-----1、进入模拟器的APIDemo展示点击输入框振动效果(views/animation/shake);
//shake 动摇;摇动;震动;握手的意思
------2、找系统sdk\samples\android-16\ApiDemos 并导入工程,如果有错误就解决;
-----3、找代码搜索代码
功能--》布局文件---》代码
-----3、找到抖动代码移植;并演示;
-----4、介绍插入器(interpolator)
------5、看APIDemo里views/animation/interpolators 的各种动画
Accelerate 加速动画 decelerate 减速动画
Interpolator类似一个函数,计算动画如何播放
/** * 系统提供的振动服务 */private Vibrator vibrator;
vibrator=(Vibrator) getSystemService(VIBRATOR_SERVICE);如果输入查询号码为空时查询,实现震动效果:
if(TextUtils.isEmpty(phone)){Toast.makeText(this, "号码为空", 0).show();Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);ed_phone.startAnimation(shake);//当电话号码为空的时候就去震动手机提醒用户vibrator.vibrate(1000);/*long[] pattern={200,200,300,300,1000,2000};vibrator.vibrate(pattern, -1);*/return;}
震动权限:
<uses-permission android:name="android.permission.VIBRATE"/>
来电号码归属地的显示
引入:1、演示打进电话,说明系统的拨号不能改。2、展示土司;
-----1、创建后台监听来电服务AddressService 并在功能清单文件注册;
检查是否有权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
-----1、在AddressService 服务里面注册来电状态
(TelephoneManager) tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
-------3、自定义监听类MyPhoneStateListener
private class MyListenerPhone extends PhoneStateListener{@Overridepublic 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(); myToast(address); break; case TelephonyManager.CALL_STATE_IDLE: //电话的空闲状态 //把这个View移出 if(view!=null){ wm.removeView(view); } break; default: break; }}}
取消监听:
tm.listen(listener, PhoneStateListener.LISTEN_NONE);listener = null;
-------3、在SettingActivity设置中心里配置设置,当点击开启的时候就启动服务,否则相反。然后演示;
布局文件:
<com.itheima.mobilesafe.ui.SettingItemView android:id="@+id/siv_show_address" itheima:title="设置号码归属地显示" itheima:desc_on="号码归属地显示已经打开" itheima:desc_off="号码归属地显示已经关闭" android:layout_width="match_parent" android:layout_height="wrap_content" />
SettingActivity里的代码:
//设置号码归属地显示
//设置归属地显示控件 siv_show_address=(SettingItemView) findViewById(R.id.siv_show_address); showAddress=new Intent(this,AddressService.class); boolean isServiceRunning=ServiceUtils.isServiceRunning(SettingActivity.this, "com.example.mobilesafe.service.AddressService"); if(isServiceRunning){ //监听来电服务是否开启的 siv_show_address.setChecked(true); }else{ siv_show_address.setChecked(false); } siv_show_address.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if(siv_show_address.isChecked()){//变为非选中状态siv_show_address.setChecked(false);stopService(showAddress);}else{//选中状态siv_show_address.setChecked(true);startService(showAddress);}}});
------3、创建一个类ServiceStatusUtils 里面的方法isServiceRunning()校验检查一个服务是否开启;
public class ServiceUtils {/* * 某个服务是否还活着 */public static boolean isServiceRunning(Context context,String serviceName){//校验服务是否还活着ActivityManager am=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);List<RunningServiceInfo> infos=am.getRunningServices(100);for(RunningServiceInfo info:infos){String name=info.service.getClassName();if(serviceName.equals(name)){return true;}}return false;}}
去电号码归属地的显示
------1、创建广播接收者OutCallReceiver 并注册;监听电话打出去的广播,需要意图;
public class OutCallReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stub//这就是我们拿到的拨出去的电话号码String phone=getResultData();//查询数据库String address=NumberAddressQueryUtils.queryNumber(phone);Toast.makeText(context, address, 1).show();}}
<receiver android:name="com.itheima.mobilesafe.receiver.OutCallReceiver"> <intent-filter > <action android:name="android.intent.action.NEW_OUTGOING_CALL"></action> </intent-filter> </receiver>
------2、需要监听具体意图和权限;
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
代码注册广播接收者
------1、演示功能:演示勾选的来电去电、 进程杀掉时的来电去电;
------2、四大组件 :
activity 、 service 、content provider、
Broadcast Receiver
都需要在功能清单文件注册。
Broadcast Receiver不仅可以在功能清单文件注册还可以用代码注册;
-------3.移植到AddressService 里和服务生命周期一样。并且演示。
注册在onCreate():
//代码注册一个广播接收者
receiver = new OutCallReceiver();IntentFilter filter = new IntentFilter();filter.addAction("android.intent.action.NEW_OUTGOING_CALL")registerReceiver(receiver, filter); 取消在onDestroy():
//代码取消注册一个广播接收者
unregisterReceiver(receiver); receiver = null;
自定义土司显示归属地
演示:目前的土司的缺陷,比如:无法控制消失、界面丑
-----1、看Toast的源代码
-----2、查看toast布局文件的背景目录:\sdk\platforms\android-16\data\res\values\themes.xml;
-----3、实现代码
private WindowManager wm;public void showMyToast(String address) {view = new TextView(this);view.setTextSize(20);view.setTextColor(Color.RED);view.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);}
------3、演示发现无法把土司一直停留页面;
------4、处理电话挂断情形
case TelephonyManager.CALL_STATE_IDLE:if(view != null){ wm.removeView(view); view = null;}break;
更改归属地的背景风格
准备:安装市场类似软件(金山软件)开启另外一个模拟器
-------1、创建布局文件toast_address.xml 图片(ic_menu_call)
-------2、借用市场软件的图片背景(call_locate_gray)
<LinearLayout android:background="@drawable/call_locate_gray" android:gravity="center_vertical" android:orientation="horizontal" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@android:drawable/ic_menu_call" /> <TextView android:id="@+id/tv_location" android:text="归属地” android:textSize="20sp" android:textColor="#000000" /> </LinearLayout>
<span style="font-size: 12px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">------3、演示金山的软件的</span>
-------4、基于ui_setting_item_view自定义点击条目(金山里去找\res\\drawable\jiantou1_pressed.png)
-------5、基于SettingItemView 自定义SettingClickView 并只处理标题和内容描述内容;
-------6、在SettingActivity 处理点击事件;
//设置归属地的背景scv_changebg = (SettingClickView) findViewById(R.id.scv_changebg);final String [] items = {"半透明","活力橙","卫士蓝","金属灰","苹果绿"};scv_changebg.setTitle("归属地提示框风格");int which = sp.getInt("which", 0);scv_changebg.setDesc(items[which]);scv_changebg.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {AlertDialog.Builder builder = new Builder(SettingActivity.this);builder.setTitle("归属地提示框风格");int which = sp.getInt("which", 0);builder.setSingleChoiceItems(items, which, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {Editor editor = sp.edit();editor.putInt("which", which);scv_changebg.setDesc(items[which]);editor.commit();dialog.dismiss();}});builder.setNegativeButton("取消", null);builder.show();}});
----------7、在实现具体的逻辑
int which = sp.getInt("which", 0);//"半透明","活力橙","卫士蓝","金属灰","苹果绿"int [] bgs = {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};view = (View) View.inflate(this, R.layout.toast_address, null);view.setBackgroundResource(bgs[which])
- 黑马程序员Android学习笔记——金山卫士项目——第四天
- 黑马程序员Android学习笔记——金山卫士项目——第二天
- 黑马程序员Android学习笔记——金山卫士项目——第一天
- 黑马程序员Android学习笔记——金山卫士项目——第三天
- 黑马程序员之手机卫士第四天
- 黑马程序员————学习笔记(第四天)
- 黑马程序员——java基础学习笔记——第四天
- 黑马程序员——>第四天<数组>
- 黑马程序员——面向对象<二> 笔记第四篇
- 黑马程序员--- 学习笔记(第四天)
- 黑马程序员--JAVA学习笔记第四天
- 黑马程序员金山卫士实战短信备份2集
- 黑马程序员——HTML学习笔记
- 黑马程序员——多线程学习笔记
- 黑马程序员——HTML学习笔记
- 黑马程序员——异常学习笔记
- 黑马程序员——HTML学习笔记
- 黑马程序员—学习笔记—接口
- 常见的MySQL命令大全(转)
- 类与泛型
- 《大数据时代》第五章读后整理和感悟
- JVM class文件结构
- android Universal-Image-Loader 图片异步加载类库的使用(超详细配置)
- 黑马程序员Android学习笔记——金山卫士项目——第四天
- eclipse 安装 hibernate插件
- centos7 安装vsftpd的步骤
- oracle小技巧,在线看oracle的错误的原因以及解决的方法
- Kicad 文件转换为 Protel 的方法
- 链表的使用
- linux装mysql数据库
- ubuntu peizhi android
- thinkphp3.2 开发(一)