手机卫士项目

手机卫士项目

下载地址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数据并封装到对象中

XmlPullJSONObjectGSON

10.分线程网络请求后UI界面更新

Thread+ Handler

11.将apk保存在sd

Environment, Context

12.读取手机联网状态

ConnectivityManager

功能二:主界面的显示相关功能

显示主界面及操作

GridView, BaseAdapter

显示带输入框的修改名称Dialog

AlertDialog

自定义名称的存储与读取

SharedPreference

显示密码设置与登陆界面

自定义内容布局的AlertDialog

密码的存储与读取

SharedPreference

密码加密处理

MD5加密

连续2back才退出应用

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)拷贝assertdb文件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);

// 获取activeNetworkInfo对象

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_PROVIDERNETWORK_PROVIDER两种

// 参数2,位置信息更新周期,单位毫秒

// 参数3,位置变化最小距离:当位置距离变化超过此值时,将更新位置信息

// 参数4,监听

// 备注:参数23,如果参数3不为0,则以参数3为准;参数30,则通过时间来定时更新;两者为0,则随时刷新

lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 1,listener);

}

9)激活应用的管理权限

l关键技术: DevicePolicyManager, DeviceAdminReceiver, <receiver>

l对于第三方应用, 如果需要做锁屏,恢复出厂设置等操作,需要提前先激活当前应用的对应管理权限

lAndroid 2.2 SDK提供了一个可管理和操作设备的APIDevicePolicyManager,使用可以接管手机的应用权限,对手机做出很多大胆的操作,比如锁屏恢复出厂设置设置密码、强制清除密码,修改密码、设置屏幕灯光渐暗时间间隔等操作。

lManifest文件中定义配置

<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,32,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调用PackageManagerhide方法实现

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>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值