- 浏览: 59545 次
- 性别:
- 来自: 北京
-
文章分类
- 全部博客 (218)
- ★★★ Android ★★★ (37)
- 【 Java 基础】✚ (0)
- ☞Java 基础概述 (0)
- ☞Java 基本语法 (0)
- ☞Java 面向对象编程 (0)
- ☞Java多线程 (0)
- ☞Java 异常处理 (0)
- ☞Java 集合框架 (0)
- ☞Java 泛型 (0)
- ☞Java 枚举和注解 (0)
- ☞Java IO流 (0)
- ☞Java 常用类 (0)
- ☞Java GUI键盘事件 (0)
- ☞Java 网络编程 (0)
- ☞Java 正则表达式 (0)
- ☞Java 反射机制 (0)
- ☞Java 小项目 (0)
- ☞Java 面试/笔试题 (0)
- 【HTML5 开发基础】✚ (0)
- ☞HTML常用标签 (0)
- ☞HTML 新特性 (0)
- ☞CSS/CSS3常用语法 (0)
- ☞JavaScript基础语法 (0)
- ☞HTML5 小项目 (0)
- ☞HTML5 面试/笔试题 (0)
- 【Android 基础阶段】✚ (12)
- ☞Android 快速入门 (1)
- ☞Android 核心组件 (1)
- ☞Android Intent (0)
- ☞Android 用户界面 (5)
- ☞Android 数据存储 (0)
- ☞Android Tomcat服务器 (0)
- ☞Android 网络编程 (2)
- ☞Android 消息机制 (0)
- ☞Android 事件机制 (0)
- ☞Fragment和ViewPager (3)
- ☞Android动画与图形处理 (0)
- ☞Android多媒体应用开发 (1)
- ☞Android 传感器开发等 (0)
- ☞Android GPS应用 (0)
- ☞Android C语言 (0)
- ☞Android JNI/NDK开发 (0)
- ☞Android Git/SVN (0)
- ☞Android 小项目 (0)
- ☞Android 面试/笔试题 (0)
- 【Android 微知识点】✚ (7)
- ☞Android 一些模版代码 (0)
- ☞Android 模块功能代码 (0)
- ☞Android UI控件大全 (2)
- ☞Android 自定义适配器 (1)
- ☞Android 自定义属性 (3)
- ☞Android 自定义动画 (0)
- ☞Android 启动过程 (0)
- ☞Android 性能优化 (0)
- ☞Android 图片三级缓存 (0)
- ☞Android 屏幕适配 (0)
- ☞Android OOM内存溢出 (0)
- ☞Android 权限 (0)
- ☞Android JNI (0)
- 【Android 网络编程】✚ (1)
- ☞Android Json解析 (2)
- ☞Android 网络请求 (2)
- 【Android 解析器】✚ (0)
- ☞Android XML (0)
- ☞Android DOM (0)
- ☞Android dom4j (0)
- ● (0)
- ●● (0)
- ●●● (0)
- ●●●● (0)
- ●●●●● (0)
- ●●●●●● (0)
- ●●●●●●● (0)
- ●●●●●●●● (0)
- ●●●●●●●●● (0)
- ☞☞☞☞☞☞☞☞☞☞ (0)
- ☞☞☞☞☞☞☞☞☞ (0)
- ☞☞☞☞☞☞☞☞ (0)
- ☞☞☞☞☞☞☞ (0)
- ☞☞☞☞☞☞ (0)
- ☞☞☞☞☞ (0)
- ☞☞☞☞ (0)
- ☞☞☞ (0)
- ☞☞ (0)
- ☞ (0)
- 【Android重量级框架】✚ (14)
- ☞框架归类 (1)
- ☞Gson (0)
- ☞xUtils3 (2)
- ☞xListView (0)
- ★ Volley (0)
- ★ AndroidAnnotations (0)
- ★ Glide (0)
- ★ SlidingMenu (0)
- ★ TabLayout (1)
- ★ ViewPagerIndicator (4)
- ★ Pulltorefresh (1)
- ★ PhotoView (1)
- ★ EventBus (0)
- ★ Vitamio5.0 (0)
- ★ Image-Loader (1)
- ★ Android-gif-drawable (0)
- ★ ActionBar (0)
- ★ ActionBarSherlock (0)
- ★ OkHttp (0)
- ★ Afinal (2)
- ★ Ffmpeg (0)
- ★ RxJava (0)
- ★ Picasso (0)
- ★ FastJson (0)
- ★ Toolbar (0)
- ★ GreenDao (0)
- ★ Otto (0)
- ★ ORMLite (0)
- ★ Retrofit (0)
- ★ Fresco (0)
- ★ SnappyDB (0)
- ★ Butterknife (0)
- ★ PagerSlidingTabStrip (0)
- PinterestLikeAdapterView (0)
- ★ NotBoringActionBar (0)
- ★ StickyListHeaders (0)
- ★ NineOldAndroids (0)
- ★ Expandablelistview (0)
- ★ SwipeRefreshLayout (0)
- ★ SwipeMenuListView (0)
- ★ (0)
- ★★ (0)
- ★★★ (0)
- ★★★★ (0)
- ★★★★★ (0)
- ★★★★★★ (0)
- ★★★★★★★ (0)
- ★★★★★★★★ (0)
- ★★★★★★★★★ (0)
- ★★★★★★★★★★ (0)
- ❉❉❉❉❉❉❉❉❉❉ (0)
- ❉❉❉❉❉❉❉❉❉ (0)
- ❉❉❉❉❉❉❉❉ (0)
- ❉❉❉❉❉❉❉ (0)
- ❉❉❉❉❉❉ (0)
- ❉❉❉❉❉ (0)
- ❉❉❉❉ (0)
- ❉❉❉ (0)
- ❉❉ (0)
- ❉ (0)
- 【第三方分享库】✚ (0)
- ○○○○○○○○○○ (0)
- ○○○○○○○○○ (0)
- ○○○○○○○○ (0)
- ○○○○○○○ (0)
- ○○○○○○ (0)
- ○○○○○ (0)
- ○○○○ (0)
- ○○○ (0)
- ○○ (0)
- ○ (1)
- 【Android开源项目】✚ (1)
- ☞综合性项目 (0)
- ☞多媒体项目 (1)
- ☞新闻性项目 (2)
- ☞社交性项目 (0)
- ☞商城性项目 (0)
- ☞Android 支付宝 (0)
- ☞Android 第三方登录 (0)
- ☞Android 语音识别 (0)
- ☞Android消息推送 (1)
- ☞Android 蓝牙 (0)
- ☞Android 传感器 (0)
- ☞Android 动画 (0)
- ☞Android 省市县三级联动 (0)
- ☞短信验证技术 (0)
- ☞二维码扫描技术 (0)
- ☂ (0)
- ☂☂ (0)
- ☂☂☂ (0)
- ☂☂☂☂ (0)
- ☂☂☂☂☂ (0)
- ☂☂☂☂☂☂ (0)
- ☂☂☂☂☂☂☂ (0)
- ☂☂☂☂☂☂☂☂ (0)
- ☂☂☂☂☂☂☂☂☂ (0)
- ☂☂☂☂☂☂☂☂☂☂ (0)
- ♣♣♣♣♣♣♣♣♣♣ (0)
- ♣♣♣♣♣♣♣♣♣ (0)
- ♣♣♣♣♣♣♣♣ (0)
- ♣♣♣♣♣♣♣ (0)
- ♣♣♣♣♣♣ (0)
- ♣♣♣♣♣ (0)
- ♣♣♣♣ (0)
- ♣♣♣ (0)
- ♣♣ (0)
- ♣ (0)
- 【Android源码分析】✚ (4)
- 【Android项目阶段】✚ (1)
- ☞Android主流架构搭建 (0)
- ☞综合性<手机安全卫士> (0)
- ☞多媒体<手机影音> (1)
- ☞新闻性<北京新闻> (0)
- ☞社交性<硅谷社交> (0)
- ☞商城性<硅谷商城> (0)
- ☞内涵段子<百思> (0)
- ☞<地图相关开发接口> (0)
- ☞下载<电子应用市场> (0)
- ☞智能<手机遥控家电> (0)
- ☞游戏<植物大战僵尸> (0)
- ☞企业实战<开源中国> (0)
- ☞Android5.0+6.0新特性 (0)
- ☞高级特效专辑 (0)
- ☞项目管理与实施 (0)
- ☞项目经验:面试/笔试题 (0)
- 【Android 前沿技术】✚ (0)
- ☞图文混排技术 (0)
- ☞百分比布局 (0)
- H5混合开发☞ (0)
- ☞APP增量升级 (0)
- ☞软件崩溃收集 (0)
- ☞前沿技术分享 (0)
- 【Android+H5混合开发】✚ (0)
- ☞React基本语法 (0)
- ☞React Native开发环境搭建 (0)
- ☞React Native开发基础 (0)
- ☞React Native常用组件 (0)
- ☞React Native常用API (0)
- ☞豆瓣搜索项目 (0)
- ☏ (0)
- ☏☏ (0)
- ☏☏☏ (0)
- ☏☏☏☏ (0)
- ☏☏☏☏☏ (0)
- ☏☏☏☏☏☏ (0)
- ☏☏☏☏☏☏☏ (0)
- ☏☏☏☏☏☏☏☏ (0)
- ☏☏☏☏☏☏☏☏☏ (0)
- ☏☏☏☏☏☏☏☏☏☏ (0)
- ☎☎☎☎☎☎☎☎☎☎ (0)
- ☎☎☎☎☎☎☎☎☎ (0)
- ☎☎☎☎☎☎☎☎ (0)
- ☎☎☎☎☎☎☎ (0)
- ☎☎☎☎☎☎ (0)
- ☎☎☎☎☎ (0)
- ☎☎☎ (0)
- ☎☎ (0)
- ☎ (0)
- 【Android+H5项目实战】✚ (0)
- 【程序员软件系列】✚ (4)
- ☞Eclipse (0)
- ☞Android Studio (4)
- ☞Genymotion (0)
- ☞Tomcat服务器 (0)
- ☞MyScal (0)
- ☀ (0)
- ☀☀ (0)
- ☀☀☀ (0)
- ☀☀☀☀ (0)
- ☀☀☀☀☀ (0)
- ☀☀☀☀☀☀ (0)
- ☀☀☀☀☀☀☀ (0)
- ☀☀☀☀☀☀☀☀ (0)
- ☀☀☀☀☀☀☀☀☀ (0)
- ☀☀☀☀☀☀☀☀☀☀ (0)
- ☻☻☻☻☻☻☻☻☻☻ (0)
- ☻☻☻☻☻☻☻☻☻ (0)
- ☻☻☻☻☻☻☻☻ (0)
- ☻☻☻☻☻☻☻ (0)
- ☻☻☻☻☻☻ (0)
- ☻☻☻☻☻ (0)
- ☻☻☻☻ (0)
- ☻☻☻ (0)
- ☻☻ (0)
- ☻ (0)
- ♬♬♬ 技术网站 ♬♬♬ (2)
- ◙ (0)
- ◙◙ (0)
- ◙◙◙ (0)
- ◙◙◙◙ (0)
- ◙◙◙◙◙ (0)
- ◘◘◘◘◘ (0)
- ◘◘◘◘ (0)
- ◘◘◘ (0)
- ◘◘ (0)
- ◘ (0)
- 【Android 其他技术】✚ (0)
- ☞Android反编译 (0)
- ☞抓包 (0)
- ☞多渠道打包及软件上线 (0)
- 【github项目/博客系列】✚ (1)
- ☞注册github步骤 (0)
- ☞github项目 (0)
- ☞优秀博客系列 (1)
- 【开发经验分享】✚ (2)
- ☞Android 知识体系 (1)
- ☞项目经验分享 (0)
- ☞面试与就业指导 (1)
- ☞Android面试技术汇总 (2)
- ♬♬♬ 词汇 ♬♬♬ (0)
- 【Android基础单词】✚ (0)
- 【javaSE单词】✚ (0)
- 【个人博客资料】✚ (0)
- 博客链接 (1)
- 快速开发 (1)
- JavaEE面试题 (1)
最新评论
手机卫士项目
手机卫士项目
下载地址:http://download.csdn.net/detail/miaozhenzhong/9622004
1.项目功能描述:
1.手机防盗功能:远程销毁数据,远程锁屏,远程警报, SIM卡变更报警, GPS追踪
2.通讯卫士: 来电和短信黑名单的管理
3.软件管理: 应用的列表展示,应用的卸载,运行与分享
4.流量管理: 显示所有应用的上传和下载流量
5.进程管理: 显示所有运行进程列表和内存占用大小,对选中的进程进行一键清理
6.缓存清理:清理缓存
7.高级工具: 手机归属地查询,短信备份与还原,程序锁和常用电话查询
8.设置中心: 手机归属地服务,归属地显示风格,归属地显示位置,程序锁服务
9.手机杀毒: 对手机中安装的所有应用进行病毒查杀,发现危险应用进行卸载
2.项目功能与技术分解
功能 |
技术点 |
功能一:欢迎界面及版本更新检查 |
|
1.使Activity界面没有标题或通知栏 |
theme, style |
2.显示界面布局 |
LinearLayout |
3.自定义旋转进度条 |
<rotate>, indeterminateDrawable |
4.得到应用的版本号 |
PackageManger |
5.显示透明,缩放,旋转动画 |
AlphaAnimation,ScaleAnimation,RotateAnimation |
6.拷贝assert下的db文件到files |
AssertManager, 文件读写 |
7.版本更新流程 |
画图分析 |
8.联网请求远程服务器数据 |
URL, HttpUrlConnection/HttpClient/Volley |
9.解析xml/json数据并封装到对象中 |
XmlPull和JSONObject或GSON |
10.分线程网络请求后UI界面更新 |
Thread+ Handler |
11.将apk保存在sd卡 |
Environment, Context |
12.读取手机联网状态 |
ConnectivityManager |
功能二:主界面的显示和相关功能 |
|
显示主界面及操作 |
GridView, BaseAdapter |
显示带输入框的修改名称Dialog |
AlertDialog |
自定义名称的存储与读取 |
SharedPreference |
显示密码设置与登陆界面 |
自定义内容布局的AlertDialog |
密码的存储与读取 |
SharedPreference |
密码加密处理 |
MD5加密 |
连续2次back键才退出应用 |
KeyEvent处理, Handler |
功能四:手机防盗的设置 |
|
设置流程 |
画图分析 |
各个设置界面 |
<RelativeLayout>,<LinearLayout> <style>, <shape><selector> |
设置界面之间的跳转动画 |
<translate>, overridePendingTransition() |
绑定当前手机中的SIM卡 |
TelephonyManager,SharedPreference, CheckBox |
显示手机联系人列表 |
ContentResolver,Phone,Cursor,ListView,BaseAdapter,ProgressDialog, Handler, Thread |
设置页面得到选择的某个联系人号 |
startActivityForResult(), onActivityResult(), setResult() |
使当前应用能获取设置管理权限 |
DevicePolicyManager, DeviceAdminReceiver, <receiver>配置 |
开机检查SIM卡有没有更换 |
BroadcastReceiver及配置, SmsManager |
短信命令实现gps追踪,远程数据销毁,远程锁屏,远程报警功能 |
短信BroadcastReceivere及配置, LocationManager,DevicePolicyManager, MediaPlayer |
功能五:手机归属地查询与来电显示 |
|
加载手机归属地数据库文件 |
流程分析, AsyncTask, ProgressDialog, SD卡文件读写 |
查询手机归属地 |
APIDemo动画效果,SQLiteDatabase, 手机号归属地规则 |
设置显示风格 |
AlertDialog, SharedPreference |
设置显示的位置 |
TouchEvent,LayoutParams, SharedPreference |
来电显示归属地 |
Service,TelephonyManager, WindowManager,LayoutParams, SharedPreference |
功能六:通讯卫士 |
|
黑名单管理 |
SqliteOpenHelper, SqliteDataBase ListActivity, ArrayAdapter ContextMenu, AlertDialog |
黑名单来电与短信拦截 |
Service, AIDL挂断电话, 短信BroadcastReceiver |
功能七:软件管理 |
|
应用的列表显示,卸载,运行与分享 |
PackageManager,Map<Boolean, List<AppInfo>>,AsyncTask, BaseAdapter, PopupWindow, 分享/卸载/运行Intent |
功能八:程序锁 |
|
应用的列表显示, 加锁与解锁 |
SqliteDatabase, TranslateAnimation, ContentProvider, ContentResolver, ContentObsver, Service, Thread,ActivityManager |
功能九:任务管理 |
|
显示系统和第三方应用进程列表 |
PackageManager, ActivityManager, AsyncTask,ListView,BaseAdapter, Map<Boolean,List<TaskInfo>> |
内存的清理 |
ActivityManager |
清理缓存的widget |
AppWidgetProvider,<appwidget-provider> RemoteView, Service, PendingIntent, Timer/TimerTask |
功能十:系统优化 |
|
清理缓存 |
PackageManager, AIDL, 反射调用@hide的方法,锁定List, 清理缓存的intent |
功能十一:流量管理 |
|
应用流量列表显示 |
SlidingDrawer, PackageManager, ResolveInfo, TrafficStats |
功能十二:高级工具 |
|
常用手机号查询 |
ExpandableListView, BaseExpandableListAdapter, AssetManager, SQLiteDatabase, 打电话Intent |
备份手机中的所有短信数据 |
ContentResolver, 短信Uri, Cursor, Gson, SD文件操作 |
还原备份的短信数据 |
同上, ProgressDialog |
功能十三:手机杀毒 |
|
理解病毒与杀毒软件 |
计算机病毒与手机病毒 杀毒软件的基本原理 |
手机杀毒的界面 |
旋转动画RotateAnimation 自定义ProgressBar 动态添加视图viewgroup.addView(view, index) |
扫描应用, 查杀病毒 |
拷贝包含病毒数据的db文件 得到所有应用的名称和签名 PackageManager 对应用签名进行MD5加密 异步查找, 同步显示进度: AsyncTask毒应用 |
3.应用功能详解
3.1.功能一: 欢迎界面及版本更新检查(难)
1)应用结构分析
在创建一个新的应用时,就需要对整个应用的包结构进行一个设计,对应用包的组织大致有两种方法
l方式一:按模块来组织代码的包结构,较大型的应用比较合适
办公软件 开会模块 com.atguigu.meeting 发工资模块 com.atguigu.money 出差模块 com.atguigu.travel |
l方式二: 按类型来组织代码的包结构,中小型应用比较合适
手机卫士: 应用界面相关 com.atguigu.ms.activity|ui 显示列表的适配器com.atguigu.ms.adapter 数据对象封装 com.atguigu.ms.bean|domain|entity 自定义视图 com.atguigu.ms.view|widget 复杂业务com.atguigu.ms.engine 数据持久化 com.atguigu.ms.dao 广播接收者 com.atguigu.ms.receiver 后台服务 com.atguigu.ms.service 内容提供者com.atguigu.ms.provider 相关工具类com.atguigu.ms.util 访问网络的类com.atguigu.ms.net|apiAPIClient |
2)界面布局
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll_welcome_root" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:gravity="bottom|center_horizontal" android:background="@drawable/logo"> <TextView android:id="@+id/tv_welcome_version" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="版本号: 1.0" android:textSize="20sp" android:textColor="#000000" android:layout_marginBottom="20dp"/> <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="50dp"/> </LinearLayout> |
3)自定义旋转进度条
l定义进度条的旋转动画,指定旋转的图片
<rotatexmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/progess"/> //注意此属性不能提示 |
l引入定义的动画
android:indeterminateDrawable="@anim/anim_loding_progress" //进度动画 android:indeterminateDuration="700" //旋转一周持续的时间 |
4)动画效果
AlphaAnimationanimation =newAlphaAnimation(0.0f, 1.0f); animation.setDuration(2000); mLinearLayout.startAnimation(animation); |
5)获取应用的当前版本号
PackageManagerpackageManager =context.getPackageManager(); PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0); String version = packageInfo.versionName; |
6)将界面设置为无标题或全屏显示
l动态编码的方式:
// 去掉窗口标题 requestWindowFeature(Window.FEATURE_NO_TITLE); // 隐藏顶部的状态栏 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(); |
l配置方式:
//方式二(不建议使用) android:theme="@android:style/Theme.Black.NoTitleBar" android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
//方式三 <stylename="AppTheme"parent="AppBaseTheme"> <itemname="android:windowNoTitle">true</item><!--没有标题--> </style> |
7)拷贝assert下的db文件到files
/** * 把assets目录下的assert下的address.db拷贝到 * /data/data/com.atguigu.ms/files/ * @paramdbname */ privatevoidcopyDB(String dbname) { File file = newFile(getFilesDir(),dbname); if(file.exists()&&file.length()>0){ Log.i (TAG, dbname+"数据库已经存在,不需要拷贝了..."); }else{ try{ InputStream is = getAssets().opendbname); FileOutputStream fos = newFileOutputStream(file); intlen = 0; bytebuffer[] =newbyte[1024]; while((len = is.read(buffer))!=-1){ fos.write(buffer, 0, len); } is.close(); fos.close(); } catch(IOException e) { e.printStackTrace(); } } } |
8)应用版本更新检查流程
画图分析
9)读取手机联网状态:
/** * 检查当前网络是否可用 */ publicstaticbooleanisNetConnected(Context context) { boolean connected = false; // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理) ConnectivityManagermanager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); // 获取active的NetworkInfo对象 NetworkInfo networkInfo = manager.getActiveNetworkInfo(); if(networkInfo!=null) { // 得到是否连接状态 connected = networkInfo.isConnected(); } returnconnected; } |
10)设计服务器端版本更新信息数据格式
lXML数据格式
<?xmlversion="1.0"encoding="UTF-8"?> <updateinfo> <version>1.0</version> <apkUrl>http://192.168.173.1:8080/SecurityServer/Security.apk</apkUrl> <desc>解决了上一个版本中的不少bug,优化了网络请求逻辑</desc> </updateinfo> |
lJSON数据格式
{ version:"1.1", apkUrl:"http://192.168.173.1:8080/SecurityServer/Security.apk", desc:"解决了上一个版本中的不少bug,优化了网络请求逻辑" } |
11)联网请求远程服务器数据
//创建url地址对象 URLurl =newURL(urlPath); //打开连接 HttpURLConnectionconnection = (HttpURLConnection) url.openConnection(); //设置可以从服务器端读取返回的数据 connection.setDoInput(true); //设置连接超时的时间 connection.setConnectTimeout(2000);//5000 //得到服务器端返回的数据流 InputStream is = connection.getInputStream(); |
12)使用XmlPull解析xml文件
privateUpdateInfo parseXml(InputStream is)throwsException { UpdateInfo info = newUpdateInfo(); XmlPullParserpullParser = XmlPullParserFactory.newInstance().newPullParser(); pullParser.setInput(is, "utf-8"); inteventType = pullParser.getEventType(); while(eventType != XmlPullParser.END_DOCUMENT) { if(eventType == XmlPullParser.START_TAG) { String tagName = pullParser.getName(); if("version".equals(tagName)) { info.setVersion(pullParser.nextText()); } elseif("apkUrl".equals(tagName)) { info.setApkUrl(pullParser.nextText()); } elseif("desc".equals(tagName)) { info.setDesc(pullParser.nextText()); } } eventType = pullParser.next(); } returninfo; } |
13)使用JsonObject解析json数据
privateUpdateInfo parseJson(InputStream is)throwsException { //将数据流封装为json对象 String jsonString = Utils.readString(is); JSONObject object = newJSONObject(jsonString);
//得到json对象中的数据封装为updateInfo对象 UpdateInfo info = newUpdateInfo(); info.setVersion(object.getString("version")); info.setApkUrl(object.getString("apkUrl")); info.setDesc(object.getString("desc"));
returninfo; }
//使用Gson框架 UpdateInfo = new Gson().fromJson(jsonString, new TypeToken<UpdateInfo>(){}.getType()) |
14)分线程网络请求后UI界面更新
//handler在主线程中处理分线程发过来的结果消息 privateHandlerhandler=newHandler() { publicvoidhandleMessage(android.os.Message msg) { switch(msg.what) { caseREQUEST_UPDATE_ERROR: break; caseREQUEST_UPDATE_SUCCESS: break; caseREQUEST_APK_ERROR: break; caseREQUEST_APK_SUCCESS: break; default: break; } } };
//启动分线程去请求服务器得到最新版本信息 newThread(newRunnable() { @Override publicvoidrun() { try{ info= APIClient.getUpdateInfo(); handler.sendEmptyMessage(REQUET_UPDATE_SUCCESS); } catch(Exception e) { e.printStackTrace(); handler.sendEmptyMessage(REQUEST_UPDATE_ERROR); } } }).start(); |
15)提示去下载和显示下载进度
/** * 显示diaog,提示用户去下载 */ privatevoidshowDownloadDialog() { newAlertDialog.Builder(this)ddd.setTitle("版本更新") .setMessage("有更新的版本,是否立即下载更新?") .setPositiveButton("下载",newDialogInterface.OnClickListener() { @Override publicvoidonClick(DialogInterface dialog,intwhich) { startDownloadApk(); } }).setNegativeButton("取消",newDialogInterface.OnClickListener() { @Override publicvoidonClick(DialogInterface dialog,intwhich) { toMain(); } }).show(); }
/** * 开启分线程下载apk,并进行安装更新 */ privatevoidstartDownloadApk() { //下载的url finalString apkUrl =info.getApkUrl(); //保存apk的本地file对象 createApkFile(); //显示下载进度的progressDialog showDownloadProgress(); newThread(newRunnable() { @Override publicvoidrun() { try{ APIClient.downloadAPK(apkUrl,apkFile,pd); handler.sendEmptyMessage(DOWNLOAD_APK_SUCCESS); } catch(Exception e) { e.printStackTrace(); handler.sendEmptyMessage(REQUEST_APK_ERROR); } } }).start(); } |
16)将apk保存在sd卡中:
File sdFile= Environment.getExternalStorageDirectory(); apkFile= newFile(sdFile,"update.apk"); /**或者**/ File filesDir= getExternalFilesDir(null); apkFile= newFile(filesDir,"update.apk"); |
17)安装APK
Intent intent = newIntent(); intent.setAction(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(apkFile),"application/vnd.android.package-archive"); context.startActivity(intent); |
18)相关权限
<!-- 读取手机联网状态的权限 --> <uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/> <!-- 读取wifi状态的权限--> <uses-permissionandroid:name="android.permission.ACCESS_WIFI_STATE"/> <!-- 请求网络的权限 --> <uses-permissionandroid:name="android.permission.INTERNET"/> <!-- sd卡操作的权限--> <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/> |
3.2.功能二: 主界面的显示和功能项名称修改
1)主界面的显示
privatestaticfinalString[]NAMES=newString[] { "手机防盗","通讯卫士","软件管理","流量管理","进程管理", "手机杀毒","缓存清理","高级工具","设置中心"}; privatestaticfinalint[]ICONS=newint[] { R.drawable.widget01, R.drawable.widget02,R.drawable.widget03, R.drawable.widget04, R.drawable.widget05, R.drawable.widget06,R.drawable.widget07, R.drawable.widget08, R.drawable.widget09}; |
<GridView android:id="@+id/gv_main" android:layout_width="match_parent" android:layout_height="wrap_content" android:numColumns="3" android:verticalSpacing="8dip"> </GridView> |
<?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="80dp" android:layout_height="80dp" android:orientation="vertical" android:gravity="center"> <ImageView android:id="@+id/iv_item_main_icon" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/ic_launcher" android:scaleType="fitXY"/> <TextView android:id="@+id/tv_item_main_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="手机防盗" android:textSize="18sp" android:layout_marginTop="2dp" android:textColor="#000000"/> </LinearLayout> |
publicView getView(intposition, View convertView, ViewGroup parent) { if(convertView ==null) { convertView = inflater.inflate(R.layout.main_item,null); } ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_item_main_icon); TextView textView = (TextView) convertView.findViewById(R.id.tv_item_main_name); imageView.setImageResource(ICONS[position]); textView.setText(NAMES[position]);
returnconvertView; } |
2)显示带输入框的Dialog
finalEditText editText =newEditText(this); editText.setHint("输入新的名称"); newAlertDialog.Builder(this) .setView(editText) .setTitle("名称修改") .setPositiveButton("确定",newDialogInterface.OnClickListener() { @Override publicvoidonClick(DialogInterface dialog,intwhich) { } }).setNegativeButton("取消",null).show(); |
3)自定义名称的存储与读取
SharedPreferencespreferences= getSharedPreferences("config", Context.MODE_PRIVATE); //保存数据 Editor edit = preferences.edit().putString("lost_name", name).commit(); //读取数据 String lostName = preferences.getString("lost_name",null); |
4)显示进入手机防盗界面的Dialog
l是否设置过密码的判断
通过SharedPreferences存储密码来实现
l设置密码的布局
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="300dip" android:background="#ffffff" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="vertical"> <TextView android:layout_width="fill_parent" android:layout_height="50dip" android:background="#E0EEEE" android:gravity="center" android:text="设置密码" android:textSize="18sp"/> <EditText android:id="@+id/et_pwd_set_pwd" android:layout_width="280dip" android:layout_height="wrap_content" android:hint="请输入密码" android:inputType="textPassword"/> <EditText android:id="@+id/et_pwd_set_confirm" android:layout_width="280dip" android:layout_height="wrap_content" android:hint="请再次输入密码" android:inputType="textPassword"/> <LinearLayout android:layout_width="280dip" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="horizontal"> <Button android:id="@+id/btn_pwd_set_confirm" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="确定"/> <Button android:id="@+id/btn_pwd_set_cancel" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="取消"/> </LinearLayout> </LinearLayout> |
l登陆的布局
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="300dip" android:background="#ffffff" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="vertical"> <TextView android:layout_width="fill_parent" android:layout_height="50dip" android:background="#E0EEEE" android:gravity="center" android:text="登 陆" android:textSize="18sp"/> <EditText android:id="@+id/et_pwd_login_pwd" android:layout_width="280dip" android:layout_height="wrap_content" android:hint="请输入密码" android:inputType="textPassword"/> <LinearLayout android:layout_width="280dip" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="horizontal"> <Button android:id="@+id/btn_pwd_login_confirm" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="确定"/> <Button android:id="@+id/btn_pwd_login_cancel" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="取消"/> </LinearLayout> </LinearLayout> |
5)自定义Button
l9patch图片的制作
1)指定patch区域(可复制区域)
2)指定能显示内容的区域
lSelector多状态图片的配置
<selectorxmlns:android="http://schemas.android.com/apk/res/android"> <itemandroid:state_pressed="true"//此item必须在前面 android:drawable="@drawable/button_pressed"/> <itemandroid:drawable="@drawable/button_normal"/> </selector> |
6)连续点击回退键,才退出应用
l监听back键的up事件
l使用Handler进行延迟消息处理
privatebooleanexit=false;//只有它为true才退出 privateHandlerhandler=newHandler(newHandler.Callback() { @Override publicbooleanhandleMessage(Message msg) { if(msg.what==1) { Log.e("TAG","2s内没有再点back"); exit= false;//2s内没有再点back,下次点back不能退出 } returnfalse; } }); @Override publicbooleanonKeyUp(intkeyCode, KeyEvent event) { if(keyCode==KeyEvent.KEYCODE_BACK) { if(!exit) { exit= true;//标识再点一次back就退出 handler.sendEmptyMessageDelayed(1, 2000); returntrue; } else{ handler.removeMessages(1); } } returnsuper.onKeyUp(keyCode, event); } |
7)对密码进行MD5加密
l对于应用中保存的密码,需要做加密处理再保存起来,这样就不至于将用户密码泄露
l项目中用得最多的一种加密方式: MD5加密 明文123456 密文
lMD5加密是将指定字符串加密为一个32位的字符串,是一个不可逆的操作
l在线MD5解密是通过保存很多明文与密文的方式来实现解密的
1. 先将指定的字符串转换为一个16位的byte[] 2. 遍历取出数组中的每个byte元素 3. 将取出的byte值与255(0xff)做与运算(&)后得到一个255以内的数值 4. 将得到的数值转换为16进制的字符串,如果它只有一位,在它的前面补0 5. 将生成的16个二位16进制形式的字符串连接起来,它就是md5加密后的32位字符串 |
publicstaticString md5(String pwd) { StringBuffer sb = newStringBuffer(); try{ //创建用于加密的加密对象 MessageDigest digest = MessageDigest.getInstance("md5"); //将字符串转换为一个16位的byte[] byte[] bytes = digest.digest(pwd.getBytes("utf-8")); for(byteb : bytes) {//遍历 //与255(0xff)做与运算(&)后得到一个255以内的数值 intnumber = b & 255;//也可以& 0xff //转化为16进制形式的字符串,不足2位前面补0 String numberString = Integer.toHexString(number); if(numberString.length()==1) { numberString = 0+numberString; } //连接成密文 sb.append(numberString); } } catch(Exception e) { e.printStackTrace(); } returnsb.toString(); } |
3.3.功能三: 手机防盗与设置(难)
1)设置流程
画图分析
2)各个设置界面布局
l关键技术点:<style>, <shape>, <RelativeLayout>, <LinearLayout>
l布局文件
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/title_background" android:orientation="vertical"> <!--标题--> <TextView android:id="@+id/tv_title" android:layout_width="fill_parent" android:layout_height="50dp" android:text="1.欢迎使用手机防盗" android:gravity="center" android:textSize="25sp" android:background="@color/title_text_color" android:layout_marginBottom="10dp"/> <TextView android:id="@+id/tv_guide_title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="您的手机防盗卫士: " android:textSize="20sp"/> <!--带星号图标的文本--> <TextView style="@style/SetupGuideContent" android:text="@string/guide1_content"/> <TextView style="@style/SetupGuideItem" android:text="@string/guide1_item1"/> <TextView style="@style/SetupGuideItem" android:text="@string/guide1_item2"/> <TextView style="@style/SetupGuideItem" android:text="@string/guide1_item3"/> <TextView style="@style/SetupGuideItem" android:text="@string/guide1_item4"/> <!--显示设置进度的图标--> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dip" android:gravity="center_horizontal" android:orientation="horizontal"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@android:drawable/presence_online" android:contentDescription="@string/hello_world"/> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@android:drawable/presence_invisible" android:contentDescription="@string/hello_world"/> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@android:drawable/presence_invisible" android:contentDescription="@string/hello_world"/> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@android:drawable/presence_invisible" android:contentDescription="@string/hello_world"/> </LinearLayout> <!—设置界面跳转的按钮--> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="5dp"> <Button android:id="@+id/btn_guide_next" android:text="@string/next" style="@style/SetupGuideNext"/> </RelativeLayout> </LinearLayout> |
l<style>的使用
<!-- 防盗功能列表项--> <stylename="SetupGuideItem"> <itemname="android:layout_width">match_parent</item> <itemname="android:layout_height">wrap_content</item> <itemname="android:textSize">18sp</item> <itemname="android:drawableLeft">@android:drawable/btn_star_big_on</item> <itemname="android:layout_marginTop">8dip</item> <itemname="android:gravity">center_vertical</item> </style> <!-- 防盗设置界面"下一步"按钮--> <stylename="SetupGuideNext"> <itemname="android:layout_width">wrap_content</item> <itemname="android:layout_height">wrap_content</item> <itemname="android:drawableRight">@drawable/next</item> <itemname="android:layout_alignParentBottom">true</item> <itemname="android:layout_alignParentRight">true</item> </style> <!-- 防盗设置界面"上一步"按钮--> <stylename="SetupGuidePre"> <itemname="android:layout_width">wrap_content</item> <itemname="android:layout_height">wrap_content</item> <itemname="android:drawableRight">@drawable/previous</item> <itemname="android:layout_alignParentBottom">true</item> <itemname="android:layout_alignParentLeft">true</item> </style> |
l<shap>的使用
<shapexmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <!-- 描边 --> <stroke android:width="0.51dip" android:color="#ffbc04e5"/> <!-- 渐变 --> <gradient android:startColor="#ffbc04e5" android:centerColor="#ffc823ed" android:endColor="#ffce30f2"/> </shape> |
3)设置界面之间的跳转动画
l关键技术: <translate>, overridePendingTransition()
<translatexmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="-100%p" android:toXDelta="0" android:duration="400"> </translate>
//启用Activity切换动画 overridePendingTransition(R.anim.translate_right_in, R.anim.translate_left_out); |
4)绑定当前手机中的SIM卡
l关键技术: TelephonyManager, SharedPreference, CheckBox
publicstaticString getSimNumber(Context context) { TelephonyManagertelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); returntelephonyManager.getSimSerialNumber(); } |
5)显示手机联系人列表:
l关键技术: ContentResolver, Phone, Cursor, ListView, BaseAdapter, ProgressDialog, Handler, Thread
/** * 得到所有联系人信息的集合 */ publicList<ContactInfo> getContactInfos() { List<ContactInfo> list = newArrayList<ContactInfo>(); ContentResolverresolver =context.getContentResolver(); String[] projection = { Phone.DISPLAY_NAME, Phone.NUMBER}; Cursorcursor = resolver.query(Phone.CONTENT_URI, projection, null,null,null); while(cursor.moveToNext()) { String name = cursor.getString(0); String number = cursor.getString(1); list.add(newContactInfo(name, number)); } cursor.close(); returnlist; } |
6)在设置页面得到选择的某个联系人号
l关键技术: startActivityForResult(), onActivityResult(), setResult()
protectedvoidonActivityResult(intrequestCode,intresultCode, Intent data) { if(requestCode==REQ_CONTACT_CODE&& resultCode==2) { //显示选择的手机号 String number = data.getStringExtra("number"); et_guide_phoneNumber.setText(number); } } |
7)开机检查SIM卡有没有更换
l关键技术: 开机BroadcastReceiver及配置, SmsManager
publicclassBootCompleteReceiverextendsBroadcastReceiver{ @Override publicvoidonReceive(Context context, Intent intent) { // 条件1:启动了防盗监听 booleanisProtected = SpUtils.getInstance(context).getBoolean(SpUtils.IS_PROTECTED,false); if(!isProtected) return; // 条件2:当前手机SIM号与保存的SIM号不一致 String currSimNumber = Utils.getSimNumber(context); String simNumber = SpUtils.getInstance(context).getString(SpUtils.SIM,null); if(simNumber !=null&& simNumber.equals(currSimNumber)) return; // 发送一个提示短信给保存的安全号 String number = SpUtils.getInstance(context).getString(SpUtils.NUMBER,null); Log.e("TAG","number="+number); if(!Utils.isEmpty(number)) { SmsManagersmsManager = SmsManager.getDefault(); smsManager.sendTextMessage(number, null,"SIM卡有变更,手机可能被盗了!",null,null); } } } |
<receiverandroid:name=".receiver.BootCompleteReceiver"> <intent-filter> <actionandroid:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> |
8)短信命令实现gps追踪,远程数据销毁,远程锁屏,远程报警功能
l关键技术: 短信BroadcastReceivere及配置, LocationManager, DevicePolicyManager, MediaPlayer
l读取接收到短信的BR类
publicclassSmsReceiverextendsBroadcastReceiver{ @Override publicvoidonReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); Object[] pdus = (Object[]) bundle.get("pdus"); byte[] pdu = (byte[]) pdus[0]; SmsMessagesmsMessage = SmsMessage.createFromPdu(pdu); String phoneNumber = smsMessage.getOriginatingAddress(); String message = smsMessage.getMessageBody(); if("#location#".equals(message)) {//gps追踪 abortBroadcast(); Log.e("TAG","回送位置信息!"); GpsUtils.sendLocation(context, safeNumber); } elseif("#reset#".equals(message)) {// 远程销毁数据(恢复出厂模式) abortBroadcast(); Log.e("TAG","远程销毁数据!"); Utils.resetPhone(context); } elseif("#lock#".equals(message)) {// 远程锁屏 abortBroadcast(); Log.e("TAG","远程锁屏!"); Utils.lockScreen(context); } elseif("#alarm#".equals(message)) {// 报警音乐 abortBroadcast(); Log.e("TAG","报警音乐!"); Utils.runAlarm(context, R.raw.jxmzf); } } } |
l注册BR
<receiverandroid:name=".receiver.SmsReceiver"> <intent-filterandroid:priority="1000"> <actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver> |
l远程销毁数据
publicstaticvoidresetPhone(Context context) { DevicePolicyManagermanager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); manager.wipeData(0); } |
l远程锁屏
publicstaticvoidlockScreen(Context context) { DevicePolicyManagermanager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); manager.resetPassword("23456", 0);//重新设置密码 manager.lockNow();//锁屏 } |
l警报音乐
publicstaticvoidrunAlarm(Context context, intresourceId) { MediaPlayermediaPlayer = MediaPlayer.create(context, resourceId); mediaPlayer.setVolume(1.0f, 1.0f);//设置最大音量 mediaPlayer.start(); } |
lGPS定位
n三种定位方式:基于卫星(gps),基于网络(network),基于基站
n基于卫星: 定位慢,准确度高,受环境影响大
北斗卫星导航系统(BDS)和美国GPS、俄罗斯GLONASS、欧盟GALILEO
n基于网络:定位快,准确度低,受环境影响小,但手机必须联网
n基于基站:误差与基站数量与远近有关
publicvoidsendLocation(Context context, String number) { this.safeNumber= number; lm= (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); // 判断GPS是否正常启动 if(!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) { MSUtils.showMsg(context,"GPS没有开启"); return; } // 获取位置信息 Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER); if(location!=null) { doublelongitude = location.getLongitude(); doublelatitude = location.getLatitude(); String result = "经度: "+longitude+",纬度: "+latitude; Log.e("TAG","发送经纬度: "+result); SmsManager.getDefault().sendTextMessage(number,null, result,null,null); } // 绑定监听 // 参数1,设备:有GPS_PROVIDER和NETWORK_PROVIDER两种 // 参数2,位置信息更新周期,单位毫秒 // 参数3,位置变化最小距离:当位置距离变化超过此值时,将更新位置信息 // 参数4,监听 // 备注:参数2和3,如果参数3不为0,则以参数3为准;参数3为0,则通过时间来定时更新;两者为0,则随时刷新 lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 1,listener); } |
9)激活应用的管理权限
l关键技术: DevicePolicyManager, DeviceAdminReceiver, <receiver>
l对于第三方应用, 如果需要做锁屏,恢复出厂设置等操作,需要提前先激活当前应用的对应管理权限
lAndroid 2.2 SDK提供了一个可管理和操作设备的API叫DevicePolicyManager,使用它可以接管手机的应用权限,对手机做出很多大胆的操作,比如锁屏、恢复出厂设置、设置密码、强制清除密码,修改密码、设置屏幕灯光渐暗时间间隔等操作。
l在Manifest文件中定义配置
<receiver android:name=".receiver.MyAdminReceiver" android:permission="android.permission.BIND_DEVICE_ADMIN"> <meta-data android:name="android.app.device_admin" android:resource="@xml/my_admin"/> <intent-filter> <actionandroid:name="android.app.action.DEVICE_ADMIN_ENABLED"/> </intent-filter> </receiver> |
l定义设备管理权限配置(/xml/my_admin)
<device-adminxmlns:android="http://schemas.android.com/apk/res/android"> <uses-policies> <limit-password/> <!--设置密码的规则--> <watch-login/> <!--监控屏幕解锁尝试次数--> <reset-password/> <!--更改屏幕解锁密码--> <force-lock/> <!—强制锁屏--> <wipe-data/> <!--删除全部数据--> <expire-password/> <!—使用密码失效--> <encrypted-storage/> <!—对存储数据进行加密--> <disable-camera/> <!—使用相机失效--> </uses-policies> </device-admin> |
l定义设备管理的receiver
publicclassMyAdminReceiverextendsDeviceAdminReceiver { } |
l启动激活
publicstaticvoidactiveDevince(Context context) { DevicePolicyManager manager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); ComponentName componentName = newComponentName(context, MyAdminReceiver.class); if(!manager.isAdminActive(componentName)) { Intent intent = newIntent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN); intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName); context.startActivityForResult(intent, 1); } } |
判断是否激活
privatebooleanisActive() { DevicePolicyManager manager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); ComponentName name = newComponentName(this, DeviceAdminSampleReceiver.class); returnmanager.isAdminActive(name); } |
10)相关权限
<!-- 请求电话状态信息 --> <uses-permissionandroid:name="android.permission.READ_PHONE_STATE"/> <!-- 读取手机联系人 --> <uses-permissionandroid:name="android.permission.READ_CONTACTS"/> <!-- 接收开机完成的广播 --> <uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <!-- 发送短信 --> <uses-permissionandroid:name="android.permission.SEND_SMS"/> <!-- 接收短信的权限 --> <uses-permissionandroid:name="android.permission.RECEIVE_SMS"/> <!-- 进行精确定位的权限 --> <uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/> |
3.4.功能四:手机归属地查询与来电显示
1)查询手机归属地
l关键技术: APIDemo动画效果, SQLiteDatabase,手机号正则表达式,手机号归属地规则
l查询规则:
n手机号:共11位数字,第一个为: 1,第二位为: 3—8,前7位决定其归属地
n匪警号码: 3位
n模拟器: 4位
n: 5位
n本地号码: 6,7,8,9位
n外地座机号:大于或等于10位,以0开头,其第2,3位或2,3,4位决定其归属地
publicstaticString getAddess(String number) { String address = number; SQLiteDatabase database = SQLiteDatabase.openDatabase(path,null, SQLiteDatabase.OPEN_READONLY); /* * 手机号: * 1. 共11位数字 * 2. 第一个为: 1 * 3. 第二位为: 3--8 */ String reg = "^1[345678]\\d{9}$"; if(number.matches(reg)) { //手机号的归属地由其前7位来查询 String sql = "select location from data2 where id=(select outkey from data1 where id=?)"; Cursor cursor = database.rawQuery(sql, newString[]{number.substring(0, 7)}); if(cursor.moveToNext()) { number = cursor.getString(0); } else{ address = "未知地区手机号"; } cursor.close(); } else{ switch(number.length()) { case3:// 110,119,120 address = "匪警号码"; break; case4:// 5554,5556 address = "模拟器"; break; case5:// 10086,10010 address = ""; break; case6: case7: case8: case9: address = "本地号码"; break; default://外地座机号 if(number.startsWith("0") && number.length()>9) { String sql = "select location from data2 where area =?"; Cursor cursor = database.rawQuery(sql, newString[]{number.substring(1, 3)}); if(cursor.moveToNext()) { String location = cursor.getString(0); address = location.substring(0, location.length()-2); break; } cursor = database.rawQuery("select location from data2 where area =?", newString[]{number.substring(1, 4)}); if(cursor.moveToNext()) { String location = cursor.getString(0); address = location.substring(0, location.length()-2); break; } cursor.close(); } break; } } returnaddress; } |
2)设置显示风格
关键技术: AlertDialog, SharedPreference
privatevoidsetStyle() { String[] items = {"半透明","活力橙","苹果绿","孔雀蓝","金属灰"}; newAlertDialog.Builder(this) .setTitle("选择颜色") .setSingleChoiceItems(items, 0,newDialogInterface.OnClickListener() { @Override publicvoidonClick(DialogInterface dialog,intwhich) { SpUtils.getInstance(AToolActivity.this) .putInt(SpUtils.BG_COLOR_INDEX, which); } }) .setPositiveButton(android.R.string.ok,null) .show(); } |
3)设置显示的位置
关键技术: TouchEvent,LayoutParams, SharedPreference
iv_drag_location.setOnTouchListener(this);
@Override publicbooleanonTouch(View v, MotionEvent event) { switch(event.getAction()) { caseMotionEvent.ACTION_DOWN: firstX= (int) event.getRawX(); firstY= (int) event.getRawY(); break; caseMotionEvent.ACTION_MOVE: intmoveX = (int) event.getRawX(); intmoveY = (int) event.getRawY(); intdistanceX = moveX -firstX; intdistanceY = moveY -firstY; intnewLeft =iv_drag_location.getLeft() + distanceX; intnewTop =iv_drag_location.getTop() + distanceY; intnewRight =iv_drag_location.getRight() + distanceX; intnewBottom =iv_drag_location.getBottom() + distanceY; iv_drag_location.layout(newLeft, newTop, newRight, newBottom); firstX= moveX; firstY= moveY; break; caseMotionEvent.ACTION_UP: intx =iv_drag_location.getLeft(); inty =iv_drag_location.getTop(); SpUtils.getInstance(this).putInt(SpUtils.LOCATION_X, x); SpUtils.getInstance(this).putInt(SpUtils.LOCATION_Y, y); break; default: break; } returntrue; } |
4)来电显示归属地
关键技术: Service,TelephonyManager, WindowManager,LayoutParams
windowManager= (WindowManager) getSystemService(Context.WINDOW_SERVICE); telephonyManager= (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); // Listen for changes to the device call state. 监听电话状态 telephonyManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE); |
privatePhoneStateListenerlistener=newPhoneStateListener() { publicvoidonCallStateChanged(intstate, String incomingNumber) { switch(state) { caseTelephonyManager.CALL_STATE_IDLE: //来电前或挂断电话后 removeAdressView(); break; caseTelephonyManager.CALL_STATE_RINGING: //响铃中 showAddress(incomingNumber); break; caseTelephonyManager.CALL_STATE_OFFHOOK: //通话中 removeAdressView(); break; default: break; } } }; |
WindowManager.LayoutParamsparams =newWindowManager.LayoutParams(); params.width= WindowManager.LayoutParams.WRAP_CONTENT;//宽度自适应 params.height= WindowManager.LayoutParams.WRAP_CONTENT;//高度自适应 params.format= PixelFormat.TRANSLUCENT;//设置成透明的 params.type= WindowManager.LayoutParams.TYPE_PHONE;//使addressView能移动 params.flags= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;//使addressView不用获得焦点 // 根据设置的位置坐标定位 intx = SpUtils.getInstance(this).getInt(SpUtils.LOCATION_X, -1); inty = SpUtils.getInstance(this).getInt(SpUtils.LOCATION_Y, -1); if(x != -1) { params.gravity= Gravity.LEFT| Gravity.TOP; params.x= x; params.y= y; } windowManager.addView(addressView, params); |
<!-- 在window添加一个视图(不是toast) -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
判断服务是否已经开启
publicstaticbooleanisServiceRunning(Context context, String className) { ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<RunningServiceInfo> runningServices = am.getRunningServices(Integer.MAX_VALUE); //取出所有运行的 for(RunningServiceInfo info : runningServices) { String serviceClassName = info.service.getClassName(); if(serviceClassName.equals(className)) { returntrue; } } returnfalse; } |
3.5.功能五: 通讯卫士
1)黑名单管理
l关键技术: SqliteOpenHelper, SqliteDataBase, Android单元测试, ListActivity, ArrayAdapter,
ContextMenu, AlertDialog
lAndorid单元测试的使用
<!-- 配置测试插件 --> <instrumentationandroid:name="android.test.InstrumentationTestRunner" android:targetPackage="com.atguigu.my_ms"/> <!-- 添加支撑测试的类库包 --> <uses-libraryandroid:name="android.test.runner"/>
//单元测试类 publicclassBlackNumberDaoTestextendsAndroidTestCase |
lContextMenu的使用
@Override publicvoidonCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { menu.add(1, 1, 1, R.string.update_number); menu.add(1, 2, 1, R.string.delete_number); } @Override publicbooleanonContextItemSelected(MenuItem item) { AdapterContextMenuInfomenuInfo = (AdapterContextMenuInfo) item.getMenuInfo(); int position = menuInfo.position; switch(item.getItemId()) { case1: showDeleteDialog(position); break; case2: dao.deleteNumber(numbers.get(position)); numbers.remove(position); adapter.notifyDataSetChanged(); break; default: break; } returnsuper.onContextItemSelected(item); } |
2)黑名单来电与短信拦截
l关键技术: Service, AIDL挂断电话,短信BroadcastReceiver, ContentResolver, ContentObersver
l添加AIDL文件:
l挂断电话
privatevoidendCall() {//挂断电话 try{ // 通过反射拿到android.os.ServiceManager里面的getService这个方法的对象 Class clazz = Class.forName("android.os.ServiceManager"); Method method = clazz.getMethod("getService", String.class); // 通过反射调用这个getService方法,然后拿到IBinder对象,然后就可以进行aidl啦 IBinder iBinder = (IBinder) method.invoke(null, newObject[] { Context.TELEPHONY_SERVICE}); ITelephony telephony = ITelephony.Stub.asInterface(iBinder); telephony.endCall(); } catch(Exception e) { e.printStackTrace(); } } |
|
l删除通话记录
l直接删除通话记录不可行,因为生成通话记录的过程是一个异步的过程,在挂断电话的瞬间,通话记录表数据还没有执行添加,只能通过Obersver来删除
privatevoiddeleteCallLog(finalString number) { final Uri uri = CallLog.Calls.CONTENT_URI; getContentResolver().registerContentObserver(uri, true, newContentObserver(null) { @Override publicvoidonChange(booleanselfChange) { getContentResolver().delete(uri, "number=?", newString[] { number }); getContentResolver().unregisterContentObserver(this); } } ); } |
<!-- 打电话的权限:用于挂断电话-->
<uses-permissionandroid:name="android.permission.CALL_PHONE"/>
<!-- 读写通话记录:用在删除通话记录-->
<uses-permissionandroid:name="android.permission.READ_CALL_LOG"/>
<uses-permissionandroid:name="android.permission.WRITE_CALL_LOG"/>
3)判断骚扰电话并显示通知
l响铃时间不超过1s
l不是联系人号
l不是黑名单
privatevoidshowNotification(String incomingNumber) { NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); Intent intent = newIntent(this, NumberSecurityActivity.class); intent.putExtra("blackNumber", incomingNumber); PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0); Notification notification =newNotification.Builder(this) .setContentTitle("发现响一声电话!") .setContentText("点击添加"+incomingNumber+"为黑名单") .setSmallIcon(R.drawable.logo) .setContentIntent(pi) .build(); manager.notify(0, notification ); } |
<!-- 读取手机联系人 -->
<uses-permissionandroid:name="android.permission.READ_CONTACTS"/>
3.6.功能六:软件管理
1)应用的列表显示
l关键技术: PackageManager,Map<Boolean, List<AppInfo>>,AsyncTask, BaseAdapter
publicMap<Boolean, List<AppInfo>> getAllAppInfos()throwsException { Map<Boolean, List<AppInfo>> map=newHashMap<Boolean, List<AppInfo>>(); List<AppInfo> systemInfos = newArrayList<AppInfo>(); map.put(true, systemInfos); //key是否是系统应用 List<AppInfo> customerInfos = newArrayList<AppInfo>();//只存储非系统的第三方应用 map.put(false, customerInfos); PackageManagerpackageManager =context.getPackageManager(); Intent intent = newIntent(); intent.setAction(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(intent, 0); for(ResolveInfo ri : resolveInfos) { String packageName = ri.activityInfo.packageName; Drawable icon = ri.loadIcon(packageManager); String appName = ri.loadLabel(packageManager).toString(); booleanisSystemApp =isSystemApp(packageManager, packageName); AppInfo appInfo = newAppInfo(icon, appName, packageName, isSystemApp); if(appInfo.isSystemApp()) { systemInfos.add(appInfo); } else { userInfos.add(appInfo); } } returnmap; } privatebooleanisSystemApp(PackageManager pm, String packageName) throwsException { PackageInfo packageInfo = pm.getPackageInfo(packageName, 0); return(packageInfo.applicationInfo.flags& ApplicationInfo.FLAG_SYSTEM) > 0; } |
2)应用的卸载,运行与分享
l关键技术: PopupWindow, 分享/卸载/运行Intent
l显示PopupWindow
popupView= View.inflate(this, R.layout.popup_view,null); ll_app_uninstall= (LinearLayout)popupView.findViewById(R.id.ll_app_uninstall); ll_app_uninstall.setOnClickListener(this); ll_app_start= (LinearLayout)popupView.findViewById(R.id.ll_app_start); ll_app_start.setOnClickListener(this); ll_app_share= (LinearLayout)popupView.findViewById(R.id.ll_app_share); ll_app_share.setOnClickListener(this); popupWindow= newPopupWindow(popupView, 240, view.getHeight()); popupWindow.setBackgroundDrawable(newColorDrawable(Color.TRANSPARENT)); popupWindow.showAsDropDown(view, 50, 0 - view.getHeight()); Animation animation = newScaleAnimation(0f, 1f, 0f, 1f); animation.setDuration(500); popupView.startAnimation(animation); |
l分享应用
privatevoidshareApp(String appName) { Intent intent = newIntent(Intent.ACTION_SEND); intent.setType("text/plain");//纯文本 //intent.putExtra(Intent.EXTRA_SUBJECT,"应用分享"); intent.putExtra(Intent.EXTRA_TEXT,"分享一个不错的应用: "+ appName);//内容 startActivity(intent); } |
l根据包名启动应用
privatevoidstartApp(String packageName) { PackageManagerpackageManager = getPackageManager(); Intent intent = packageManager.getLaunchIntentForPackage(packageName); if(intent ==null) { Utils.showToast(this,"此应用无法启动"); } else{ startActivity(intent); } } |
l根据包名卸载应用
privatevoiduninStallApp(AppInfo appInfo) { if(appInfo.isSystemApp()) { Toast.makeText(this,"系统应用不能卸载!", 0).show(); } elseif(getPackageName().equals(appInfo.getPackageName())) { Toast.makeText(this,"当前应用不能卸载!", 0).show(); }else{ Intent intent = newIntent(Intent.ACTION_DELETE); intent.setData(Uri.parse("package:" + appInfo.getPackageName())); startActivity(intent); } } |
l监视应用的卸载
receiver= newUninstallReceiver(); IntentFilter filter = newIntentFilter(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package");//package:com.atguigu.ms this.registerReceiver(receiver, filter);
privateclassUninstallReceiverextendsBroadcastReceiver { @Override publicvoidonReceive(Context context, Intent intent) { String dataString =intent.getDataString();//package:com.atguigu.ms if(dataString!=null) { AppInfo appInfo =newAppInfo(); appInfo.packageName= dataString.substring(dataString.indexOf(":")+1); userInfos.remove(appInfo); adapter.notifyDataSetChanged(); } } } |
3.7.功能七:程序锁(难)
1)应用的列表显示, 加锁与解锁
l关键技术: SqliteDatabase, ListView, BaseAdapter, TranslateAnimation
Service, ActivityManager
ContentProvider, ContentResolver,ContentObserver,
@Override publicvoidonItemClick(AdapterView<?> parent, View view,intposition,longid) { // 添加动画效果,动画结束后,就把锁的图片改变 TranslateAnimationanimation =newTranslateAnimation(Animation.RELATIVE_TO_SELF, 0f,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f); animation.setDuration(500); view.startAnimation(animation);//向右水平快速移动后复原 AppInfo appInfo = appInfoList.get(position); ViewHolder viewHolder = (ViewHolder) view.getTag(); booleanlock = (Boolean) viewHolder.lockIV.getTag(); if(lock) { viewHolder.lockIV.setImageResource(R.drawable.unlock); viewHolder.lockIV.setTag(false); lockedApps.remove(appInfo.getPackageName()); Uri uri = Uri.parse("content://com.atguigu.security.provider.applockprovider/delete"); getContentResolver().delete(uri,null,newString[] { appInfo.getPackageName() }); } else{ viewHolder.lockIV.setImageResource(R.drawable.lock); viewHolder.lockIV.setTag(true); lockedApps.add(appInfo.getPackageName()); ContentValues values = newContentValues(); values.put("packagename", appInfo.getPackageName()); Uri uri = Uri.parse("content://com.atguigu.security.provider.applockprovider/insert"); getContentResolver().insert(uri, values); } } |
2)监听锁定应用的启动
l关键技术: 流程分析ContentProvider, ContentResolver, ContentObsver, Service, Thread,ActivityManager
lAppLockMonitorService-----启动监听线程(一直运行)
n获取最新启动的应用信息
n判断它是否需要锁定
n如果是, 启动解锁界面
n适当的睡眠
/** * 开启一直运行的子线程监听 */ privatevoidstartMonitor() { newThread(newRunnable() { @Override publicvoidrun() { while (flag){ // 1. 得到当前最近启动的应用packageName String packageName = getCurrentPackageName(); Log.e("TAG","start pn="+ packageName); try{ // 2. 判断是否需要锁定此应用 // 判断是否在临时不锁定的列表中,如果是不用显示解锁界面 // 如果在,启动一个锁屏界面(LockScreenActivity) if(!tempUnlockNames.contains(packageName) && appLockNames.contains(packageName)) { startLockScreenActivity(packageName); } Thread.sleep(100); } catch(InterruptedException e) { e.printStackTrace(); } } } }).start(); }
privateStringgetTopPackageName() { returnam.getRunningTasks(1).get(0).topActivity.getPackageName(); }
privatevoidstartLockScreenActivity(String packageName) { Intent intent = newIntent(this, LockScreenActivity.class); //intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//必须是此flag intent.putExtra("packagename", packageName); startActivity(intent); } |
lAppLockProvider-----为应用锁表数据编写ContentProvider
@Override publicUriinsert(Uri uri, ContentValues values) { intmatch =matcher.match(uri); if(match ==1) { String packageName = values.getAsString("packagename"); appLockDao.add(packageName); //通知所有监听在此URI上的obsever getContext().getContentResolver().notifyChange(URI,null); } else{ thrownewRuntimeException("格式不正确"); } returnnull; } @Override publicintdelete(Uri uri, String selection, String[] selectionArgs) { intmatch =matcher.match(uri); if(match ==1) { appLockDao.delete(selectionArgs[0]); //通知所有监听在此URI上的obsever getContext().getContentResolver().notifyChange(URI, null); } else{ thrownewRuntimeException("格式不正确"); } return0; } |
lAppLockActiviy-----通过ContentResolver向应用锁表中添加或删除记录
//删除数据 Uri uri = Uri.parse("content://com.atguigu.my_ms.provider.applockprovider/applock"); getContentResolver().delete(uri, null,newString[] { appInfo.getPackageName() }); //添加记录 ContentValues values = newContentValues(); values.put("packagename", appInfo.getPackageName()); Uri uri = Uri.parse("content://com.atguigu.my_ms.provider.applockprovider/applock"); getContentResolver().insert(uri, values); |
lAppLockMonitorService-----监听应用锁表数据的变化
Uri uri = Uri.parse("content://com.atguigu.security.provider.applockprovider"); getContentResolver().registerContentObserver(uri, true, observer);
protectedContentObserverobserver=newContentObserver(newHandler()) { publicvoidonChange(booleanselfChange) { appLockNames= appLockDao.getAll(); Log.e("TAG","ContentObserver onChange().."); } }; |
lLockScreenActivity ----密码验证与解锁通知
Intent service = newIntent(this, AppLockMonitorService.class); service.putExtra("packageName",packageName); startService(service ); |
3.8.功能八:进程管理
1)显示系统和第三方应用进程列表
l关键技术: PackageManager, ActivityManager,AsyncTask,ListView,
BaseAdapter,List<ProcessInfo>
l得到所有正在运行的进程的信息
publicstaticvoidgetAllProcessInfos(Context context, List<ProcessInfo> systemProcessInfos, List<ProcessInfo> userProcessInfos) { ActivityManageram = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE); List<RunningAppProcessInfo> processInfos = am.getRunningAppProcesses(); PackageManagerpm = context.getPackageManager(); for(RunningAppProcessInfo processInfo : processInfos) { ProcessInfo info = newProcessInfo(); // 包名 String packageName = processInfo.processName; info.setPackageName(packageName); // 应用占用的内存bit/byte MemoryInfo memoryInfo = am .getProcessMemoryInfo(newint[] { processInfo.pid})[0]; longmemInfoSize = memoryInfo.getTotalPrivateDirty() * 1024; info.setMemInfoSize(memInfoSize); try{ // 图标 Drawable icon = pm.getPackageInfo(packageName, 0).applicationInfo.loadIcon(pm); info.setIcon(icon); // 应用名称 String name = pm.getPackageInfo(packageName, 0).applicationInfo .loadLabel(pm).toString(); info.setAppName(name); // 是否是系统应用进程 intflag = pm.getPackageInfo(packageName, 0).applicationInfo.flags; if((flag & ApplicationInfo.FLAG_SYSTEM) == 0) {//用户进程 info.setSystem(false); } else{//系统进程 info.setSystem(true); } } catch(NameNotFoundException e) {//根据包名得到不到PackageInfo e.printStackTrace(); info.setIcon(context.getResources().getDrawable(R.drawable.icon)); info.setAppName(packageName); info.setSystem(true); } //不同类型的Info保存到不同的集合中 if(info.isSystem()) { systemProcessInfos.add(info); } else{ userProcessInfos.add(info); } } } |
l得到手机中可用内存大小
publicstaticlonggetAvailMem(Context context) { ActivityManageram = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo outInfo = newActivityManager.MemoryInfo(); am.getMemoryInfo(outInfo); returnoutInfo.availMem; } |
l得到手机中总内存大小
@TargetApi(Build.VERSION_CODES.JELLY_BEAN) publicstaticlonggetTotalMem(Context context) { longtotalMem = 0; intsysVersion = VERSION.SDK_INT;//得到当前系统的版本号 // 下面的方式只能在JELLY_BEAN(16)及以上版本才有用 if(sysVersion >= Build.VERSION_CODES.JELLY_BEAN) { ActivityManager am = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo memoryInfo = newActivityManager.MemoryInfo(); am.getMemoryInfo(memoryInfo); totalMem = memoryInfo.totalMem; } else{ try{//在版本小于16时,读取/proc/meminfo文件的第一行来获取总大小 File file = newFile("/proc/meminfo"); FileInputStream fis = newFileInputStream(file); BufferedReader reader = newBufferedReader( newInputStreamReader(fis)); String result = reader.readLine();// MemTotal: 510484 kB result = result.substring(result.indexOf(":") + 1, result.indexOf("k")).trim();// 510484 reader.close(); totalMem = Integer.parseInt(result) * 1024; } catch(Exception e) { e.printStackTrace(); } } returntotalMem; } |
l文件大小格式化
//返回格式化后的大小:1.5GB,12MB,16.66KB,0.00B 101010101byte String Formatter.formatFileSize(context,byteSize); |
2)进程的清理
l关键技术: ActivityManager
//根据包名杀死对应的进程 activityManager.killBackgroundProcesses(packageName) |
<!-- 杀死后台进程 -->
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
3)清理进程的widget
l关键技术: AppWidgetProvider,<appwidget-provider>, RemoteView, Service,
PendingIntent, Handler
lAppWidgetProvider : 接收widget工具添加到桌面或从桌面移除等广播的receiver
publicclassProcessWidgetextendsAppWidgetProvider{ privateIntentintent; @Override publicvoidonEnabled(Context context) {//长按产生一个widget intent= newIntent(context,UpdateWidgetService.class); context.startService(intent); } @Override publicvoidonDeleted(Context context,int[] appWidgetIds) {//移除桌面的widget if(intent!=null) { context.stopService(intent); intent= null; } } } |
l注册receiver
<receiverandroid:name=".receiver.ProcessWidget"> <intent-filter> <actionandroid:name="android.appwidget.action.APPWIDGET_UPDATE"/></intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/process_widget"/> </receiver> |
l应用小工具的配置文件
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/process_widget" android:minHeight="72dp" android:minWidth="294dp"> </appwidget-provider> |
lUpdatewidgetService 用于更新widget的服务
@Override publicvoidonCreate() { super.onCreate();/* //创建用于更新widget的管理器 manager= AppWidgetManager.getInstance(this); //包含widget视图布局的远程视图对象 remoteViews= newRemoteViews(getPackageName(), R.layout.process_widget_view); //为widget中的button添加点击监听 Intent intent = newIntent(this,UpdatewidgetService.class); intent.putExtra("clear",true); PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0); remoteViews.setOnClickPendingIntent(R.id.btn_widget_clear, pendingIntent); //准备用于更新widget的组件对象 componentName= newComponentName(this, ProcessWidget.class); //更新widget updateWidget(); //发送延迟消息,使用widget能每隔2秒更新一次 handler.sendEmptyMessageDelayed(1, 2000); } |
privatevoidupdateWidget() { MSUtils.log("updateWidget()..."); processCount= MSUtils.getProcessCount(this);//进程大小 remoteViews.setTextViewText(R.id.tv_widget_process_count,"进程数为 " + processCount); availMem= MSUtils.getAvailMem(this);//可用内存大小 remoteViews.setTextViewText(R.id.tv_widget_process_memory,"可用内存为 " + Formatter.formatFileSize(this,availMem)); manager.updateAppWidget(componentName,remoteViews); } |
l使用BroadcastReceiver使应用更省电
privateScreeenReceiverreceiver; privatevoidregistScreenReceiver() { receiver= newScreeenReceiver(); IntentFilter filter = newIntentFilter(); filter.addAction(Intent.ACTION_SCREEN_ON); //开屏 filter.addAction(Intent.ACTION_SCREEN_OFF);//锁屏 registerReceiver(receiver, filter ); } privateclassScreeenReceiverextendsBroadcastReceiver{ @Override publicvoidonReceive(Context context, Intent intent) { String action = intent.getAction(); if(Intent.ACTION_SCREEN_ON.equals(action)) { Log.e("TAG","开屏...."); handler.removeCallbacksAndMessages(null); handler.sendEmptyMessage(1); } else{ Log.e("TAG","锁屏...."); handler.removeCallbacksAndMessages(null); } } } |
l为应用生成桌面快捷方式
privatevoidcreateShortcut() { //得到是否生成快捷图标的标识 booleanshortcut = SpUtils.getInstance(this) .getBoolean(SpUtils.SHORT_CUT,false); if(!shortcut) { Intent intent = newIntent("com.android.launcher.action.INSTALL_SHORTCUT"); //图标 intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, BitmapFactory.decodeResource(getResources(), R.drawable.logo)); //名称 intent.putExtra(Intent.EXTRA_SHORTCUT_NAME,"手机卫士"); //点击快捷键,启动哪个界面 Intent callIntent = newIntent("com.atguigu.my_ms.action.Main"); intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, callIntent); //发送广播,桌面(laucher)应用有Receiver接收并生成桌面图标 sendBroadcast(intent); //保存已生成快捷图标的标识 SpUtils.getInstance(this).put(SpUtils.SHORT_CUT,true); } } <!-- 生成应用快捷方式 --> <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /> |
3.9.功能九: 缓存清理
1)得到应用的安装包,数据和缓存大小
关键技术: PackageManager, AIDL, 反射调用@hide的方法
l得到应用的cache大小
//得到安装的所有应用 List<ApplicationInfo> applications = pm.getInstalledApplications(0);
//得到某个应用的缓存数据 Method method = PackageManager.class.getMethod("getPackageSizeInfo", String.class,IPackageStatsObserver.class); method.invoke(pm, packageName,newIPackageStatsObserver.Stub() { @Override publicvoidonGetStatsCompleted(PackageStatspStats,booleansucceeded) { long cacheSize = pStats.cacheSize); } }); |
l权限: android.permission.GET_PACKAGE_SIZE
2)清理缓存
l通过反射+AIDL调用PackageManager的hide方法实现
l只能是系统应用使用,第三方应用不能使用
Method method = PackageManager.class.getMethod("deleteApplicationCacheFiles", String.class, IPackageDataObserver.class); method.invoke(pm, info.packageName,newIPackageDataObserver.Stub(){ @Override publicvoidonRemoveCompleted(String packageName, booleansucceeded)throwsRemoteException { } }}); |
l调用系统设置应用清理缓存
Intent intent = newIntent(); intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); intent.setData(Uri.parse("package:"+cacheInfos.get(position).getPackageName())); startActivity(intent); |
3.10.功能十: 流量管理
1)应用流量列表显示:
l关键技术:SlidingDrawer, PackageManager, ApplicationInfo, TrafficStats
/** * 得到应用的所有流量信息 */ publicstaticList<TrafficInfo> getAllTrafficInfos(Context context) { List<TrafficInfo> list = newArrayList<TrafficInfo>(); PackageManagerpm = context.getPackageManager(); //安装的所有应用(包含没有主界面的) List<ApplicationInfo> infos = pm.getInstalledApplications(0); for(ApplicationInfo info : infos) { TrafficInfo trafficInfo = newTrafficInfo(); //appName String appName = info.loadLabel(pm).toString(); trafficInfo.setName(appName); //icon Drawable icon = info.loadIcon(pm); trafficInfo.setIcon(icon); intuid = info.uid; //userID //inSize 下载流量 longinSize =TrafficStats.getUidRxBytes(uid); //receive trafficInfo.setInSize(inSize); //outSize 上传流量 longoutSize =TrafficStats.getUidTxBytes(uid); trafficInfo.setOutSize(outSize); list.add(trafficInfo); } returnlist;7 } |
//根据应用的id得到其下载流量和上传流量 longuidRxBytes =TrafficStats.getUidRxBytes(uid); longuidTxBytes = TrafficStats.getUidTxBytes(uid); //得到手机总的下载流量和上传流量(2g/3g/wifi) longtotalRxBytes = TrafficStats.getTotalRxBytes(); //receive longtotalTxBytes = TrafficStats.getTotalTxBytes(); //得到手机的下载流量和上传流量(2g/3g) longmobileRxBytes = TrafficStats.getMobileRxBytes(); longmobileTxBytes = TrafficStats.getMobileTxBytes(); |
3.11.功能十一: 高级工具
1)常用手机号查询
l关键技术: ExpandableListView, BaseExpandableListAdapter, SQLiteDatabase,打电话Intent
<ExpandableListView android:id="@+id/elv_list" android:layout_width="match_parent" android:layout_height="match_parent" android:groupIndicator="@drawable/expendable_group_selector"/>
<selectorxmlns:android="http://schemas.android.com/apk/res/android"> <!-- 展开时显示 --> <itemandroid:drawable="@drawable/group_list" android:state_expanded="true"/> <!-- 不展开显示 --> <itemandroid:drawable="@drawable/group_list_pressed"/> </selector> |
2)备份手机中的所有短信数据
l技术: ContentResolver, 短信Uri, Cursor, XmlSerializer, XmlPullParser Gson
l保存为xml文件格式
<?xmlversion="1.0"encoding="utf-8"standalone="yes"?> <smses> <sms> <address>445</address> <date>1423316911894</date> <type>2</type> <body>R56yy</body> </sms> <sms> <address>234</address> <date>1423316902099</date> <type>2</type> <body>Wrtt</body> </sms> </smses> |
l读取短信数据(查看mmssms.db数据库)
ContentResolver resolver = context.getContentResolver(); Uri uri = Uri.parse("content://sms"); String[] projection = {"address","date","type","body"}; Cursor cursor = resolver.query(uri , projection , null,null,null); |
lXmlSerializer的使用样例
// 创建用于生成xml数据的对象 XmlSerializerserializer =Xml.newSerializer(); try{ //设置文件输出流 OutputStream os = newFileOutputStream(smsFile); serializer.setOutput(os,"utf-8"); //开始写文档 serializer.startDocument("utf-8",true); //写<smses> serializer.startTag(null,"smses"); while(cursor.moveToNext()) { //写<sms> serializer.startTag(null,"sms"); String address = cursor.getString(0); String date = cursor.getString(1); String type = cursor.getString(2); String body = cursor.getString(3); //写<address>abc</address> createTag(serializer, "address", address); createTag(serializer, "date", date); createTag(serializer, "type", type); createTag(serializer, "body", body); //写</sms> serializer.endTag(null,"sms"); } //写</smses> serializer.endTag(null,"smses"); //结束写文档 serializer.endDocument(); } catch(Exception e) { e.printStackTrace(); }
privatevoidcreateTag(XmlSerializer serializer, String tagName, String value) throwsException { serializer.startTag(null, tagName); //写文本标签体 serializer.text(value); serializer.endTag(null, tagName); } |
3)还原备份的短信数据
l技术: ContentResolver, 短信Uri, XmlPullParser,ProgressDialog
lXmlPullParser使用样例
try{ //创建pull解析器 XmlPullParserpullParser = Xml.newPullParser(); //设置xml文件流 pullParser.setInput(fis ,"utf-8"); //读取第一个事件类型 inteventType = pullParser.getEventType(); //不断循环读取,直到文档最后 while(eventType!=XmlPullParser.END_DOCUMENT) { String tagName = null; switch(eventType) { caseXmlPullParser.START_TAG://开始标签 //得到标签名 tagName = pullParser.getName(); if("address".equals(tagName)) { //保存<address>的文本标签体内容 values.put("address", pullParser.nextText()); } elseif("date".equals(tagName)) { values.put("date", pullParser.nextText()); } elseif("type".equals(tagName)) { values.put("type", pullParser.nextText()); } elseif("body".equals(tagName)) { values.put("body", pullParser.nextText()); } break; caseXmlPullParser.END_TAG://结束标签 tagName = pullParser.getName(); if("sms".equals(tagName)) { //如果读到</sms>,就将数据保存到短信表中 resolver.insert(uri, values); } break; default: break; } //解析下一个单元数据,并保存其事件类型 eventType = pullParser.next(); } } catch(Exception e) { e.printStackTrace(); } |
3.12.功能十二: 手机杀毒
1)计算机病毒与手机病毒
对电脑有破坏性的程序 |
|
目地: 显摆技术,验证技术 |
|
指通过特定的程序(木马程序)来控制另一台计算机 目的:利益,账号:银行账号,游戏账号。 |
|
一种具有传染性、破坏性的手机程序.其可利用发送短信、彩信,电子邮件,浏览网站,下载铃声,蓝牙等方式进行传播,会导致用户手机死机、关机、个人资料被删、向外发送垃圾邮件泄露个人信息、自动拨打电话、发短(彩)信等进行恶意扣费,甚至会损毁SIM卡、芯片等硬件,导致使用者无法正常使用手机 目地:利益 |
2)杀毒软件
l作用: 用来定位出带病毒的软件应用,并提示用户将它们给删除。
l基本原理:
n收集病毒保存起来形成强大的病毒库, 如果安装的应用在病毒库中有记录, 杀毒软件就会提示其是病毒(手机杀毒)
n它会监视软件的行为来判断其是否可能是病毒
1.监听是否开机启动
2.监听软件是否有打开摄像头
3.是否发邮件
4.是否很特别占用资源
3)得到安装应用的信息
//得到所有包(包括已删除但安装目录还存在的) List<PackageInfo> packages = pm.getInstalledPackages(PackageManager.GET_SIGNATURES); for(PackageInfo packInfo : packages){ //应用名称 info.name= packInfo.applicationInfo.loadLabel(pm).toString(); //应用包名 info.packacgeName= packInfo.packageName; //应用签名 String signature = packInfo.signatures[0].toCharsString(); } |
4)判断是否是病毒
//对应用签名进行md5加密 signature = MSUtils.md5(signature); //查询病毒库表 String desc = AntiVirusQueryDao.getDesc(getApplicationContext(), signature); if(desc==null) {//不是 info.isVirus=false; } else{//是 info.isVirus=true; } |
5)扫描杀毒时的旋转动画
RotateAnimationra =newRotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f); ra.setDuration(1000); ra.setRepeatCount(RotateAnimation.INFINITE);//播放无限次 iv_antivirus_scanning.startAnimation(ra); |
6)自定义水平进度条
定义包含进度条图片的drawable文件
<layer-listxmlns:android="http://schemas.android.com/apk/res/android"> <itemandroid:id="@android:id/background" android:drawable="@drawable/security_progress_bg"> </item> <itemandroid:id="@android:id/secondaryProgress" android:drawable="@drawable/security_progress_bg"> </item> <itemandroid:id="@android:id/progress" android:drawable="@drawable/security_progress"> </item> </layer-list> |
相关推荐
### 手机卫士项目知识点概述 #### 一、项目功能描述 - **手机防盗功能:** - **远程销毁数据:** 当手机丢失时,可通过远程指令彻底删除手机内的所有数据,保护用户隐私。 - **远程锁屏:** 通过发送特定指令使...
《手机卫士项目源码深度解析》 手机卫士,作为一个综合性的安全应用,其核心功能包括手机防盗、软件管理、任务管理、高级工具以及设置中心。这些功能的实现涉及了移动安全领域的多个方面,同时也是Android开发的...
【Android代码-安卓学习之手机卫士项目】 在Android开发领域,"手机卫士"项目是一种常见的实战练习,旨在帮助开发者提升系统优化、安全防护以及性能监控等方面的技术能力。在这个项目中,我们将深入探讨Android应用...
【标题】"仿百度手机卫士项目"是一个实践性的IT项目,旨在开发一款类似于百度手机卫士的应用程序。这样的项目通常涵盖了移动安全领域的多个关键功能,例如病毒查杀、垃圾清理、内存优化、隐私保护、应用管理等。通过...
传智播客_Andorid_Android项目手机卫士视频video_day09视频.rar
android版手机安全卫士项目详细源代码。 这是android一个有详细代码和注释的项目,手机安全卫士,不管你是新手还是大神,都有一定的参考价值 android 项目 源代码。
Android项目实战 手机安全卫士.part2 由于上传限制,此书籍采用分卷压缩,需要与 Android项目实战 手机安全卫士.part1一起才能正常解压使用
在手机卫士项目中,活动通常用于展示用户界面,服务可能用于后台运行的安全扫描,广播接收器则可以监听系统事件,如开机启动或接收到特定消息时执行安全检查。 二、用户界面设计 在Android Studio中,开发者通常...
在手机卫士项目中,可能会涉及到读取、写入存储、访问网络等敏感权限,理解并正确处理这些权限至关重要。 其次,我们将学习如何创建自定义的广播接收器(BroadcastReceiver)。广播接收器允许应用监听系统或应用事件...
本站之前发布过几套基于安卓的手机卫士项目源码, 本项目是仿金山手机卫士源码 ,里面各种技术,能学到很多东西,不懂的可以问作者,不多说,先上图,要把数据库导入的啊,不然会报错的,没有任何问题,大多数控件...
在手机卫士项目中,需要考虑应用的启动速度、内存占用和电池消耗等问题。这包括使用AsyncTask进行后台操作,避免主线程阻塞,以及使用ProGuard对代码进行混淆和优化。 通过这个Day04的视频教程,学员不仅能够掌握...
在手机卫士项目中,Intent可能用于启动扫描病毒、清理内存等功能。 5. **权限管理**:由于手机卫士涉及到系统级别的操作,如扫描病毒或管理内存,开发者需要了解如何在AndroidManifest.xml中声明和管理权限。 6. *...
在手机卫士项目中,需要设计直观且友好的界面,让用户轻松操作。 9. **异步编程**:为了保证用户体验,耗时的操作(如扫描病毒)应放在后台线程进行。可以使用AsyncTask、Handler、Thread或更现代的Coroutines进行...
教程名称:手机安全卫士项目开发视频课程目录:【】手机安全卫士_day1【】手机安全卫士_day2【】手机安全卫士_day3【】手机安全卫士_day4【】手机安全卫士_day5【】手机安全卫士_day6【】手机安全卫士_day7【】手机...
在本资源中,“传智播客_Andorid_Android项目手机卫士视频video_day08视频.zip”是一个针对Android开发的教程,特别是聚焦于构建一个名为“手机卫士”的应用程序。这个项目旨在帮助用户理解如何在Android平台上创建...
在“手机卫士”的开发过程中,第五天的任务主要集中在提升用户体验上,这涉及到实现归属地的拖拽效果、设置归属地的位置以及归属地浮窗的设计与实现。这些功能的优化对于一个全面的手机安全应用至关重要,因为它们...
在这个手机卫士项目中,我们可能会看到以下几个关键组件: 1. **Activity**:作为用户界面的主要入口,手机卫士可能包含多个Activity,如主界面、设置页面、扫描结果展示页等。每个Activity对应一个屏幕视图,并...
总之,Android项目实战中的"手机卫士"涉及到多方面的技术,包括权限管理、内容提供者、数据库操作、网络通信等。开发者需要掌握扎实的Android基础知识,才能构建出高效、稳定且用户友好的安全应用。