手机卫士涉及的知识点总结

Splash界面

splash: 溅,洒

  • 展现产品的logo提升产品的知名度
  • 初始化操作(创建数据库,读取配置文件)
  • 连接服务器检查软件授权
  • 连接服务器检查软件的更新

自动更新的前提

  • 包名一致
  • 签名一致

状态选择器

整体取消掉标题栏:在清单文件中加一修改主题

android:theme=”@android:style/Theme.Light.NoTitleBar”

PackageManager:获取各种包的信息(版本、应用程序图标、包信息等)

开源项目框架:

xUtils-2.6.8.jar 断点下载

使用:

HttpUtils httputils=new HttpUtils();
httputils.download(url,target,autoResume,callback);
//url:下载的路径
//targer:存放的路径sd
//autoResume:true是否断点续传
//callback:下载回传
new RequestCallBack<File>(){重写onSuccess();重写onFailure();重写onload();//显示下载进度在textview中当前/总进度
}

开源项目断点下载xUtils耗时操作

            HttpUtils http=new HttpUtils();final File file=new File(Environment.getExternalStorageDirectory(),"xxx.apk");http.download(data.downLoadUrl, file.getAbsolutePath(), true, new RequestCallBack<File>(){//下载失败@Overridepublic void onFailure(HttpException arg0, String arg1) {}//下载成功@Overridepublic void onSuccess(ResponseInfo arg0) {//下载成功,替换安装模板代码ToastUtils.show(SplashActivity.this, "下载成功");Intent intent=new Intent();intent.setAction("android.intent.action.VIEW");intent.addCategory("android.intent.category.DEFAULT");intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");startActivity(intent);}});

下载替换安装只要调用系统的应用就行:(模板代码)

Itent intent=new Intent();
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");
startActivity(intent);

市面上常用界面-九宫格

状态选择器:

就是在res目录下建立一个drawable文件中定义一个xml文件,设置属性background时引用这个xml文件就行。

//背景颜色选择<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@android:color/darker_gray" android:state_pressed="true">   //按住时<item android:drawable="@android:color/darker_gray" android:state_focused="true">  //聚焦时<item android:drawable="@android:color/transparent" >  //默认状态</item>
</item>
</item>
</selector>

按住图标显示不一样的图片,新建一个tupian.xml文件,引用图标时R.drawable.tupian.xml

//图标状态选择<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@drawable/app_pressed" android:state_pressed="true">   //按住时<item android:drawable="@drawable/app_focused"android:state_focused="true">  //聚焦时<item android:drawable="@drawable/app" >   //默认状态</item>
</item>
</item>
</selector>

走马灯效果按钮

Button可实现,当点击按钮的时候滚动起来
设置属性

android:focusableInTouchMode="true"
android:ellipsize="marquee"
android:text="显示的内容"

TextView也可以实现滚动走马灯:需要自定义TextView,实现里面的所有构造函数并重写isFocused()直接返回true

@Override
@ExportedProperty(category = "focus")
public boolean isFocused() {return true;
}

并设置下面几个属性

<com.cca.mobilephone.ui.FocusedTextView     android:ellipsize="marquee"android:focusableInTouchMode="true"android:layout_width="match_parent"android:layout_height="wrap_content"android:singleLine="true"android:text="希望我所认识的亲戚朋友远离病痛,远离饥饿,走上富康的道路,过上幸福的的生活!"
/>

这样textview跑马灯效果就可以跑起来了

设置一条线可以使用View

自定义组合控件:textView+checkBox 下面还有一条分割线

public class SettingCheckView extends LinearLayout {public SettingCheckView(Context context, AttributeSet attrs) {super(context, attrs);initial(context);String bigtitle=attrs.getAttributeValue("http://schemas.android.com/apk/res/com.cca.mobilephone", "bigtitle");TextView tv_title=(TextView) findViewById(R.id.tv_ui_setting);tv_title.setText(bigtitle);}
public SettingCheckView(Context context) {super(context);initial(context);
}
private void initial(Context context) {this.setOrientation(LinearLayout.VERTICAL);//this.addView(View.inflate(context, R.layout.ui_setting_view, null));
}
}

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/rl_set_update"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="center_vertical"
android:background="@drawable/background" ><TextViewandroid:id="@+id/tv_ui_setting"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginLeft="10dp"android:text="开启自动更新"android:textSize="20sp" /><CheckBoxandroid:id="@+id/cb_set_update"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:layout_marginRight="20dp"android:clickable="false"android:focusable="false" /><Viewandroid:layout_width="match_parent"android:layout_height="0.1dp"android:layout_margin="2dp"android:background="#88000000" /></RelativeLayout>

使用时:

<com.cca.mobilephone.ui.SettingCheckViewandroid:layout_width="match_parent"android:layout_height="wrap_content"mobilephone:bigtitle="我是功能2"/>

自定义属性:

先声明属性命名空间

  xmlns:mobilephone="http://schemas.android.com/apk/res/com.cca.mobilephone"

在values定义一个attrs.xml文件,在里面声明功能

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SettingCheckView"><attr name="bigtitle" format="string"/>
</declare-styleable>//或者<declare-styleable name="SettingCheckView"><attr name="title" format="string"/>
</declare-styleable></resources>

做到这里就可以使用自定义组合控件了,功能可以设置文本内容,想增加其他的属性,在attrs中定义出来就可以使用了。

自定义对话框:

    AlertDialog.Builder builder=new Builder(context);View dialogview=View.inflate(context, R.layout.show_setup_dialog, null);builder.setView(view);builder.show();

//高低版本默认的背景色和字体颜色不一样、使高低版本保持一致的样式需
设置其背景色、文本字体色

AlertDialog.Builder builder=new Builder(MainActivity.this);View dialogview=View.inflate(context, R.layout.show_setup_dialog, null);AlertDialog dialog=builder.create();dialog.setView(dialogview,0,0,0,0);//设置对话框上下左右的距离dialog.show();

show_setup_dialog的xml布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="wrap_content"android:orientation="vertical" ><TextView android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#BFFF01"android:text="设置密码"android:textSize="30dp"android:gravity="center"/><EditText android:gravity="center_horizontal"android:layout_width="300dp"android:layout_height="wrap_content"android:hint="请输入密码"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"android:inputType="textPassword"/><EditText android:gravity="center_horizontal"android:layout_width="300dp"android:layout_height="wrap_content"android:hint="请确定密码"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"android:inputType="textPassword"/><LinearLayout android:layout_width="300dp"android:layout_height="wrap_content"><Button android:layout_width="0dp"android:layout_weight="1"android:background="@drawable/btn_background"android:text="取消"android:layout_marginRight="5dp"android:layout_height="wrap_content"/><Button android:layout_width="0dp"android:layout_weight="1"android:layout_marginLeft="5dp"android:background="@drawable/btn_background"android:text="确定"android:layout_height="wrap_content"/></LinearLayout></LinearLayout>

自定义背景选择器:btn_background.xml(要放在drawable文件下)

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@android:color/holo_blue_light" android:state_pressed="true"><item android:drawable="@android:color/holo_blue_light" android:state_focused="true"><item android:drawable="@android:color/transparent" ></item></item></item></selector>

当有很多个界面有相同的方法,相同的布局时,都要存储数据时,可定义一个父类让其他的类来继承它

动画的切换效果:

//一句代码,必须要放在Activity或者finish()的后面
overridePendingTransition(R.anim.trans_next_in, R.anim.trans_next_out);

在res目录下建立一个anim文件夹:创建两个xml:trans_next_in.xml和trans_next_out.xml如下

<?xml version="1.0" encoding="utf-8"?>
<translatexmlns:android="http://schemas.android.com/apk/res/android"android:fromXDelta="100%p"android:toXDelta="0"android:toYDelta="0"android:fromYDelta="0"android:duration="300">
</translate><?xml version="1.0" encoding="utf-8"?>
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="-100%p"
android:toYDelta="0"
android:fromYDelta="0"
android:duration="300">
</translate>

手势识别器

1、先声明一个手势识别器

private GestureDetector  mGestureDetector;

2、初始化一个手势识别器

//2、初始化手势识别器mGestureDetector=new GestureDetector(getApplicationContext(), new GestureDetector.SimpleOnGestureListener(){@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2,float velocityX, float velocityY) {/*** e1、手指触摸屏幕的一瞬间* e2、手指离开屏幕的一瞬间* velocityX、velocityY:水平方向和竖直方向的速度* */if((e1.getRawX()-e2.getRawX())>150){showNext();overridePendingTransition(R.anim.trans_next_in, R.anim.trans_next_out);return true;}if((e2.getRawX()-e1.getRawX())>150){showPre();overridePendingTransition(R.anim.trans_pre_in, R.anim.trans_pre_out);return true;}return super.onFling(e1, e2, velocityX, velocityY);}});

3、第三步、使用户识别手势器的动作

//第三步、使用手势识别器识别用户的动作
@Override
public boolean onTouchEvent(MotionEvent event) {mGestureDetector.onTouchEvent(event);return super.onTouchEvent(event);
}

绑定手机卡、获取手机序列号,一个手机号对应一个序列号

//用到一个系统的服务
private TelephonyManager tm=(TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
//获取手机序列号
String sim=tm.getSimSerialNumber();

电话联系人

data/data/com.android.providers.contacts.database.contacts2.db

对应三张表:

查找联系人工具类:

public class ContactsInfoUtils {public static List<ContactsInfo> getContactsInfo(Context context){List<ContactsInfo> infocontacts=new ArrayList<ContactsInfo>();//获取内容提供者的解析器ContentResolver resolver=context.getContentResolver();Uri uri=Uri.parse("content://com.android.contacts/raw_contacts");Uri dataUri=Uri.parse("content://com.android.contacts/data");//游标Cursor cursor=resolver.query(uri, new String[]{"contact_id"}, null, null, null);//遍历游标集合while(cursor.moveToNext()){String id=cursor.getString(0);System.out.println("id"+id);ContactsInfo infos=new ContactsInfoUtils().new ContactsInfo();Cursor datacursor=resolver.query(dataUri, new String[]{"data1"}, "raw_contact_id=?", null, null);while(datacursor.moveToNext()){String data1=datacursor.getString(0);String mimetype=datacursor.getString(1);if("vnd.android.cursor.item/name".equals(mimetype)){//姓名infos.name=data1;}else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){//电话infos.phone=data1;}else if("vnd.android.cursor.item/email_v2".equals(mimetype)){//电话infos.email=data1;}}infocontacts.add(infos);}return infocontacts;}
public class ContactsInfo{public String name;public String email;public String phone;
}
}

密码加密:md5 单向加密,不可逆原文–>密文

public static String encode(String text){try {MessageDigest digest=MessageDigest.getInstance("md5");String password="234";byte[] result=digest.digest(password.getBytes());StringBuffer sb=new StringBuffer();for(byte b:result){String hex=Integer.toHexString(b&0xff)+2;//加盐更好更安全if(hex.length()==1){sb.append("0");}sb.append(hex);}return sb.toString();} catch (NoSuchAlgorithmException e) {e.printStackTrace();return "";}
}

播放报警音乐:便捷方式:src下新建目录raw可放音乐文件

    MediaPlayer mediaplayer=MediaPlayer.create(context, R.raw.uri);//循环播放mediaplayer.setLooping(true);//设置音量最大声mediaplayer.setVolume(1.0f, 1.0f);mediaplayer.start();abortBroadcast();

超级管理员:

Android 2.2引入了支持企业应用程序提供Android设备管理API。设备管理API提供了设备管理功能在系统水平。这些api允许您创建安全性敏感的应用程序是有用的在企业环境中,IT专业人员需要丰富的控制员工的设备。例如,内置Android电子邮件应用程序利用了新的api来改善交流的支持。通过电子邮件应用程序,交流管理员可以执行密码策略——包括字母数字密码或数字针——在设备。管理员也可以远程擦除(即恢复工厂默认值)丢失或被盗的手机。用户可以同步他们的电子邮件和日历数据交换。
Email client
Security application that to remove wipe
Device management service and application

一键锁屏应用:能够一键锁屏,一键卸载

步骤:

1、先创建admim类继承DeviceAdminReceiver

2、配置清单文件(参考api文档)

 <receiverandroid:name="com.cca.yijian.Admin"android:description="@string/sample_device_admin_description"android:label="@string/sample_device_admin"android:permission="android.permission.BIND_DEVICE_ADMIN" ><!-- 元数据,提供设备的超级管理员的配置信息 --><meta-dataandroid:name="android.app.device_admin"android:resource="@xml/device_admin_sample" /><intent-filter><action android:name="android.app.action.DEVICE_ADMIN_ENABLED" /></intent-filter></receiver>

还要新建一个 res目录下xml文件夹并新建device_admin_sample.xml:
声明中使用的安全策略的元数据提供了特定于设备管理员的附加信息,可通过DeviceAdminInfo类进行解析查看,以下为device_admin_sample.xml:的内容

<device-admin xmlns: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>

3、主活动中书写代码

点击按钮一键锁屏:

  public void lockscreen(View view){DevicePolicyManager dpm=(DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);ComponentName who=new ComponentName(this, Admin.class);if(dpm.isAdminActive(who)){//重置密码//dpm.resetPassword("123", 0);//清除sd卡数据//dpm.wipeData(DevicePolicyManager.WIPE_EXTERNAL_STORAGE);dpm.lockNow();finish();}else{Toast.makeText(this, "请先激活应用程序", 0).show();}}

使用时:先来到系统设置界面,找到安全、进入设备管理器、找到一键锁屏,点击激活一键锁屏,此时可以使用了。

先激活应用程序

给用户一个很好的体验:来个按钮“先激活应用程序”

    Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);ComponentName who=new ComponentName(this, Admin.class);intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, who);intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,"请大家赶紧去激活程序吧,首次激活有大礼包!");startActivity(intent);

一键卸载

再来个卸载按钮:

public void deleteLockScreen(View view){DevicePolicyManager dpm=(DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);ComponentName who=new ComponentName(this, Admin.class);dpm.removeActiveAdmin(who);Intent intent=new Intent();intent.setAction(Intent.ACTION_DELETE);intent.setData(Uri.parse("package:"+getPackageName()));startActivity(intent);
}

获取位置的经纬度(真实标准坐标)在中国要转换成火星坐标才能真正确定位置

 protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//获取位置内容提供者LocationManager lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);Criteria criteria=new Criteria();//指定高精度criteria.setAccuracy(Criteria.ACCURACY_FINE);//指定高耗电量criteria.setPowerRequirement(Criteria.POWER_HIGH);//获取最好的内容提供者String provider =lm.getBestProvider(criteria, true);lm.requestLocationUpdates(provider, 0, 0, new LocationListener() {//状态改变时调用@Overridepublic void onStatusChanged(String provider, int status, Bundle extras) {   }//可用时调用@Overridepublic void onProviderEnabled(String provider) {}   @Overridepublic void onProviderDisabled(String provider) {}       @Overridepublic void onLocationChanged(Location location) {      location.getLatitude();//纬度location.getLongitude();//经度System.out.println("纬度:"+location.getLatitude()+"------经度:"+location.getLongitude());TextView text=new TextView(getApplication());text.setTextColor(Color.RED);text.setText("纬度:"+location.getLatitude()+"------经度:"+location.getLongitude());}} );}

标准坐标—->>中国的火星坐标

使用算法:导入modifyOffset.java和axisoffset.dat

直接到代码中使用:

ModifyOffset no =ModifyOffset.getInstance(context.getClassLoader().getResourceAsStream("axisoffset.dat"));//真实坐标X经度 Y为纬度
//不过查找时外国网站经度放在围纬度后面:纬度,经度PointDouble pt =new PointDouble(x,y);
PointDouble marpoint=mo.s2c(pt);System.out.println(marpoint.toString());
//输出的是x=。。。。,y=。。。。。经纬度

listView的简单优化

容易内存溢出

1、尽量复用convertview历史的缓存,减少创建新的view对象

2、尽量的减少子孩子的id的查询次数,定义一个viewHolder

View view;
viewHolder holder;
if(convertView!=null){//复用历史的view对象view=convertView;holder=(viewHolder) view.getTag();
}else{//创建新的孩子时加上标签holder=new viewHolder();view=View.inflate(getApplicationContext(), R.layout.item_callsmssafe, null);holder.black_phone=(TextView) view.findViewById(R.id.tv_black_phone);holder.black_mode=(TextView) view.findViewById(R.id.tv_black_mode);view.setTag(holder);}
//内部类
class viewHolder{public TextView black_phone;public TextView black_mode;public ImageView black_delete;
}

listView显示数据库中的数据时,当listview发生变化时应更新listview数据

//通知listview更新数据
adapter.notifyDataSetChanged();

在清单文件中配置广播接收者的特点是:不管应用程序进程是否存在都能接受到对应广播

短信拦截:开启服务并在里面注册一个广播接收者

开启服务:
Intent intent=new Intent(SettingActivity.this,CallSmsSafeService.class);startService(intent);

//服务里面代码动态注册一个广播接收者

public class CallSmsSafeService extends Service {private BlackNumberDao dao;private InnerReceiver receiver;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {dao=new BlackNumberDao(this);//动态注册receiver=new InnerReceiver();IntentFilter filter=new IntentFilter();//设置关心短信到来的动作filter.addAction("android.provider.Telephony.SMS_RECEIVED");filter.setPriority(Integer.MAX_VALUE);//代码注册广播接收者registerReceiver(receiver, filter);System.out.println("黑名单短信拦截开启了!!!!!");super.onCreate();}@Overridepublic void onDestroy() {super.onDestroy();unregisterReceiver(receiver);receiver=null;}//内部类广播接收者private class InnerReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {//拦截短信Object[] objs=(Object[]) intent.getExtras().get("pdus");for(Object obj:objs){SmsMessage smsMessage=SmsMessage.createFromPdu((byte[])obj);String address=smsMessage.getOriginatingAddress();String result=dao.find(address);if("2".equals(result)||"3".equals(result)){System.out.println("黑名单短信拦截模式。。。");abortBroadcast();}//智能拦截String body=smsMessage.getMessageBody();if(body.contains("天使")){//分词算法SmsManager.getDefault().sendTextMessage("13531829360", null, "帮你拦截了天使客一条消息", null, null);abortBroadcast();}}}}
}

服务断电就会自动停止,用sp存储不会保存状态,读取系统的的运行信息,调用系统的活动和服务管理者ActivityManager可以判断服务是否正在后台运行

/*** 判断系统的服务是否在后台运行* context:上下文* StringName: 服务的全路经名*/
public static boolean isServiceRunning(Context context,String StringName){ActivityManager am=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);List<RunningServiceInfo> infos=am.getRunningServices(100);for(RunningServiceInfo info:infos){String className=info.service.getClassName();if(StringName.equals(className)){return true;}}return false;
}

分词算法:
开源算法:
luncence

利用反射原理挂断电话

    /*** 挂断电话的方法,利用反射*/public void endCall() {try {Class clazz=CallSmsSafeService.class.getClassLoader().loadClass("android.os.ServiceManager");Method method=clazz.getDeclaredMethod("getService", String.class);IBinder ibinder=(IBinder) method.invoke(null, TELEPHONY_SERVICE);ITelephony iTelephony=ITelephony.Stub.asInterface(ibinder);iTelephony.endCall();} catch (Exception e) {e.printStackTrace();}}

删除通话的记录(内容观察者)

//监视呼叫记录的的数据库,看什么时候生成了,
//就把它删除
Uri uri=Uri.parse("content://call_log/calls");
getContentResolver().registerContentObserver(uri, true,new ContentObserver(new Handler()) {@Overridepublic void onChange(boolean selfChange) {super.onChange(selfChange);deleteCallLog(incomingNumber);}
});/*** 删除拨号记录* @param incomingNumber*/
public void deleteCallLog(String incomingNumber) {ContentResolver resolver=getContentResolver();Uri uri=Uri.parse("content://call_log/calls");resolver.delete(uri, "number=?", new String[]{incomingNumber});
}

打断点、看内存、查源码

电话的拦截功能:

    /*** 定义电话管理的服务*/
private TelephonyManager tm;
private MyPhoneStateListener listener;/*** 实例化电话管理的服务*/tm=(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);//注册电话的监听器listener=new MyPhoneStateListener();//监听电话的状态的改变tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);

监听器的注册

class MyPhoneStateListener extends PhoneStateListener{@Overridepublic void onCallStateChanged(int state, String incomingNumber) {super.onCallStateChanged(state, incomingNumber);switch(state){case TelephonyManager.CALL_STATE_IDLE://空闲状态break;case TelephonyManager.CALL_STATE_RINGING://响铃状态String mode=dao.find(incomingNumber);if(mode.equals("1")||mode.equals("3")){System.out.println("挂断电话");}break;case TelephonyManager.CALL_STATE_OFFHOOK://接听状态break;}}}

ActivityManager:获取进程和服务的管理

ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE) ;    //获得系统运行的进程
List<ActivityManager.RunningAppProcessInfo> appList1 = mActivityManager  .getRunningAppProcesses();
for (RunningAppProcessInfo running : appList1) {  System.out.println(running.processName);
}
System.out.println("================");  //获得当前正在运行的service
List<ActivityManager.RunningServiceInfo> appList2 = mActivityManager  .getRunningServices(100);
for (ActivityManager.RunningServiceInfo running : appList2) {  System.out.println(running.service.getClassName());
}  System.out.println("================");  //获得当前正在运行的activity
List<ActivityManager.RunningTaskInfo> appList3 = mActivityManager  .getRunningTasks(1000);
for (ActivityManager.RunningTaskInfo running : appList3) {  System.out.println(running.baseActivity.getClassName());
}
System.out.println("================");  //获得最近运行的应用
List<ActivityManager.RecentTaskInfo> appList4 = mActivityManager  .getRecentTasks(100, 1);
for (ActivityManager.RecentTaskInfo running : appList4) {  System.out.println(running.origActivity.getClassName());  }

判断某个进程或服务是否在后台进行的工具类:

package com.cca.mobilephone.Utils;
import java.util.List;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;
public class ServicerUtils {/*** 判断系统的服务是否在后台运行*/
public static boolean isServiceRunning(Context context,String StringName){ActivityManager am=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);List<RunningServiceInfo> infos=am.getRunningServices(1000);for(ActivityManager.RunningServiceInfo info:infos){String className=info.service.getClassName();System.out.println(className);if(StringName.equals(className)){System.out.println(className);return true;}}return false;
}

}

数据库的增删改查

package com.cca.mobilephone.db.dao;import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;import com.cca.mobilephone.db.BlackNumberOpenHeloper;
import com.cca.mobilephone.domain.BlackNumberInfo;public class BlackNumberDao {private BlackNumberOpenHeloper openhelper;/*** 数据库的构造函数* @param context*/
public BlackNumberDao(Context context) {super();openhelper=new BlackNumberOpenHeloper(context);
}/*** 往数据库中增加号码* @param phone 增加的电话号码* @param mode  模式* @return*/
public boolean add(String phone,String mode){SQLiteDatabase db=openhelper.getWritableDatabase();     ContentValues values=new ContentValues();values.put("phone", phone);values.put("mode", mode);long id=db.insert("blacknumberinfo", null, values);db.close();if(id!=-1){return true;}else{return false;}}/*** 修改黑名单的拦截模式* @param phone 要修改的黑名单号码* @param newmode 新的拦截模式* @return 修改是否成功*/
public boolean update(String phone,String newmode){SQLiteDatabase db=openhelper.getWritableDatabase();ContentValues values=new ContentValues();values.put("mode", newmode);int rowcount=db.update("blacknumberinfo", values, "phone=?", new String[]{phone});db.close();if(rowcount==0){return false;}else{return true;}
}
/*** 查找黑名单号码的拦截模式* @param phone 要查找的电话号码* @return  返回拦截的模式*/
public String find(String phone){String mode=null;SQLiteDatabase db=openhelper.getReadableDatabase();Cursor cursor=db.query("blacknumberinfo", null, "phone=?", new String[]{phone},null, null, null);if(cursor.moveToNext()){mode=cursor.getString(cursor.getColumnIndex("mode"));;}cursor.close();db.close();return mode;}/*** 删除黑名单号码* @param phone  要删除的号码* @return  是否删除成功*/public boolean delete(String phone){SQLiteDatabase db=openhelper.getWritableDatabase();int rowcount=db.delete("blacknumberinfo", "phone=?", new String[]{phone});db.close();if(rowcount==0){return false;}{return true;}
}
/*** 返回全部的黑名单信息* @return*/
public List<BlackNumberInfo> findAll(){SQLiteDatabase db=openhelper.getReadableDatabase();Cursor cursor=db.query("blacknumberinfo", null, null, null, null, null, "_id desc");List<BlackNumberInfo> infos=new ArrayList<BlackNumberInfo>();while(cursor.moveToNext()){String phone=cursor.getString(cursor.getColumnIndex("phone"));String mode=cursor.getString(cursor.getColumnIndex("mode"));BlackNumberInfo info=new BlackNumberInfo();info.setPhone(phone);info.setMode(mode);infos.add(info);}cursor.close();db.close();return infos;
}

分批加载

/*** 分批加载返回的黑名单信息* @return*/
public List<BlackNumberInfo> findPart(int startIndex,int maxCount){SQLiteDatabase db=openhelper.getReadableDatabase();Cursor cursor=db.rawQuery("select _id,phone,mode from blacknumberinfo order by _id desc limit ? offset ?", new String[]{String.valueOf(maxCount),String.valueOf(startIndex)});List<BlackNumberInfo> infos=new ArrayList<BlackNumberInfo>();while(cursor.moveToNext()){String phone=cursor.getString(cursor.getColumnIndex("phone"));String mode=cursor.getString(cursor.getColumnIndex("mode"));BlackNumberInfo info=new BlackNumberInfo();info.setPhone(phone);info.setMode(mode);infos.add(info);}cursor.close();db.close();return infos;
}

分页加载解决内存溢出

/*** 分页加载返回的黑名单信息* @return*/
public List<BlackNumberInfo> findPagper(int pagper){SQLiteDatabase db=openhelper.getReadableDatabase();Cursor cursor=db.rawQuery("select _id,phone,mode from blacknumberinfo order by _id desc limit ? offset ?", new String[]{String.valueOf(10),String.valueOf(pagper*10)});List<BlackNumberInfo> infos=new ArrayList<BlackNumberInfo>();while(cursor.moveToNext()){String phone=cursor.getString(cursor.getColumnIndex("phone"));String mode=cursor.getString(cursor.getColumnIndex("mode"));BlackNumberInfo info=new BlackNumberInfo();info.setPhone(phone);info.setMode(mode);infos.add(info);}cursor.close();db.close();return infos;
}/*** 获取全部总条目* @return*/public int getTotalCount(){SQLiteDatabase db=openhelper.getReadableDatabase();Cursor cursor=db.rawQuery("select count(*) from blacknumberinfo ",null);cursor.moveToNext();int total=cursor.getInt(0);cursor.close();db.close();return total;
}
}

复制资产目录下的文件到android系统下

    /*** 拷贝资产目录下的数据库到Android系统下*/
private void copyDB(final String name) {/** 数据库多时可能耗时*/new Thread(){public void run() {File file=new File(getFilesDir(),name);if(file.exists()&&file.length()>0){System.out.println("数据库已经加载过,无需在加载!");}else{try {InputStream is=getAssets().open(name);FileOutputStream fos=new FileOutputStream(file);byte[] buffer=new byte[1024];int len=-1;while((len=is.read(buffer))!=-1){fos.write(buffer, 0, len);}is.close();fos.close();} catch (Exception e) {e.printStackTrace();}}};}.start();
}

自定义吐司

    /*** 自定义吐司* @param address*/
public void showToast(String address) {WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);View view = View.inflate(getApplicationContext(), R.layout.item_toast, null);//设置背景,字体等自定义属性int which=getSharedPreferences("config", 0).getInt("which", 0);int bgs[]={R.drawable.btn_gray_normal,R.drawable.btn_green_normal,R.drawable.btn_gray_pressed,R.drawable.call_show_bg,R.drawable.btn_disabled};view.setBackgroundResource(bgs[which]);TextView tv_address=(TextView) view.findViewById(R.id.tv_address);tv_address.setText(address);
//设置参数paramsWindowManager.LayoutParams params = new WindowManager.LayoutParams();params.height = WindowManager.LayoutParams.WRAP_CONTENT;params.width = WindowManager.LayoutParams.WRAP_CONTENT;params.format = PixelFormat.TRANSLUCENT;params.type = WindowManager.LayoutParams.TYPE_TOAST;params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;wm.addView(view, params);}

及时退出吐司的显示用:wm.removeView(view);

控件的拖拽效果

ImageView imgview= (ImageView) findViewById(R.id.imageview);
imgview.setOnTouchListener(new OnTouchListener() {int startx;int starty;@Overridepublic boolean onTouch(View v, MotionEvent event) {switch(event.getAction()){case MotionEvent.ACTION_DOWN://手指第一次触摸控件时调用//获取控件在屏幕上的坐标startx=(int) event.getRawX();starty=(int) event.getRawY();break;case MotionEvent.ACTION_MOVE://手指在控件上移动的事件//手指移动后的偏移量int newx=(int) event.getRawX();int newy=(int) event.getRawY();int dx=newx-startx;int dy=newy-starty;//移动后的控件新坐标imgview.layout(imgview.getLeft()+dx, imgview.getTop()+dy, imgview.getRight()+dx, imgview.getBottom()+dy);//移动后重新初始化控件坐标startx=(int) event.getRawX();starty=(int) event.getRawY();System.out.println("移动了控件"+startx+"---"+starty);break;case MotionEvent.ACTION_UP://手指离开控件的一瞬间break;}return true;}});

简单双击效果实现

btn=(Button) findViewById(R.id.btn);btn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if(firsttime>0){secondtime=System.currentTimeMillis();if((secondtime-firsttime)<500){Toast.makeText(getApplicationContext(), "双击了", 0).show();firsttime=0;}else{firsttime=0;}return ;}firsttime=System.currentTimeMillis();new Thread(){public void run() {try {Thread.sleep(500);firsttime=0;} catch (InterruptedException e) {e.printStackTrace();}};}.start();}});

多次点击事件实现

//定义了多长的数组就是多次点击,3就是连续3击
private long[] mHits=new long[3];
/**
*四个参数:源数组,从第几个开始拷贝,目标数组,从第几个开始拷贝,拷贝的长度
*
*/
System.arraycopy(mHits, 1, mHits, 0, mHits.length-1);
mHits[mHits.length-1] = SystemClock.uptimeMillis();
if (mHits[0] >= (SystemClock.uptimeMillis()-500)) {Toast.makeText(getApplicationContext(), "多次击了", 0).show();
}

自定义吐司加上拖拽的效果图显示

    /*** 自定义吐司* @param address*/
public void showToast(String address) {wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);view = View.inflate(getApplicationContext(), R.layout.item_toast, null);view.setOnTouchListener(new OnTouchListener() {int startx ;int starty ;@SuppressWarnings("deprecation")@Overridepublic boolean onTouch(View v, MotionEvent event) {switch(event.getAction()){case MotionEvent.ACTION_DOWN://手指触摸//获取自定义吐司坐标startx=(int) event.getRawX();starty=(int) event.getRawY();break;case MotionEvent.ACTION_UP://手指离开//存储控件的位置坐标SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);Editor edit=sp.edit();edit.putInt("lastx", params.x);edit.putInt("lasty", params.y);edit.commit();break;case MotionEvent.ACTION_MOVE://手指移动//获取偏移量int newx=(int) event.getRawX();int newy=(int) event.getRawY();int dx=newx-startx;int dy=newy-starty;params.x +=dx;params.y +=dy;//判断view控件是否移出屏幕范围if(params.x>(wm.getDefaultDisplay().getWidth()-view.getWidth())){params.x=wm.getDefaultDisplay().getWidth()-view.getWidth();}if(params.y>(wm.getDefaultDisplay().getHeight()-view.getHeight())){params.x=wm.getDefaultDisplay().getHeight()-view.getHeight();}wm.updateViewLayout(view, params);//重新初始化控件坐标startx=(int) event.getRawX();starty=(int) event.getRawY();break;}return true;}});//设置背景颜色int which=getSharedPreferences("config", 0).getInt("which", 0);int bgs[]={R.drawable.btn_gray_normal,R.drawable.btn_green_normal,R.drawable.btn_gray_pressed,R.drawable.call_show_bg,R.drawable.btn_disabled};view.setBackgroundResource(bgs[which]);TextView tv_address=(TextView) view.findViewById(R.id.tv_address);tv_address.setText(address);params = new WindowManager.LayoutParams();params.height = WindowManager.LayoutParams.WRAP_CONTENT;params.width = WindowManager.LayoutParams.WRAP_CONTENT;params.format = PixelFormat.TRANSLUCENT;//左上对齐params.gravity=Gravity.LEFT+Gravity.TOP;SharedPreferences sp=getSharedPreferences("config", MODE_PRIVATE);params.x=sp.getInt("lastx", 0);params.y=sp.getInt("lasty", 0);params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;wm.addView(view, params);}

可扩展的ListView(ExpandableListView控件)

public class QuerryUsualNumber extends Activity {private ExpandableListView exl_listview;private SQLiteDatabase db;private TextView tv;private MyExpandableAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);db=SQLiteDatabase.openDatabase("/data/data/com.cca.mobilephone/files/commonnum.db", null, SQLiteDatabase.OPEN_READONLY);setContentView(R.layout.activity_querryusualnumber);exl_listview = (ExpandableListView) findViewById(R.id.exl_listview);adapter = new MyExpandableAdapter();//设置适配器exl_listview.setAdapter(adapter);//孩子被点击的监听器exl_listview.setOnChildClickListener(new OnChildClickListener() {@Overridepublic boolean onChildClick(ExpandableListView parent, View v,int groupPosition, int childPosition, long id) {//点击条目获得数据库返回的数据,并分割提取号码进行拨号                    String data=UsualNumberDao.getChildrenNameByPosition(db, groupPosition, childPosition);String datas[]=data.split("\n");String name=datas[0];String number=datas[1];Toast.makeText(getApplicationContext(), groupPosition+"--"+childPosition+":"+name+":"+number, 0).show();//点击之后进行拨打指定号码的电话Intent intent =new Intent();intent.setAction(Intent.ACTION_CALL);intent.setData(Uri.parse("tel:"+number));startActivity(intent);return true;}});
}

适配器

private class MyExpandableAdapter extends BaseExpandableListAdapter{/*** 获取分组的个数*/@Overridepublic int getGroupCount() {return UsualNumberDao.getGroupCount(db);}/*** 获取每个分组的孩子的个数*/@Overridepublic int getChildrenCount(int groupPosition) {return UsualNumberDao.getChildGroupCount(db,groupPosition);}@Overridepublic Object getGroup(int groupPosition) {return null;}@Overridepublic Object getChild(int groupPosition, int childPosition) {return null;}@Overridepublic long getGroupId(int groupPosition) {return 0;}@Overridepublic long getChildId(int groupPosition, int childPosition) {return 0;}@Overridepublic boolean hasStableIds() {return false;}/*** 返回每个分组的view对象*/@Overridepublic View getGroupView(int groupPosition, boolean isExpanded,View convertView, ViewGroup parent) {//TextView tv;if(convertView==null){tv=new TextView(QuerryUsualNumber.this);}else{tv=(TextView) convertView;}tv.setTextSize(25);tv.setTextColor(Color.RED);tv.setText("      "+UsualNumberDao.getNameByGroupCountposition(db,groupPosition));return tv;}@Overridepublic View getChildView(int groupPosition, int childPosition,boolean isLastChild, View convertView, ViewGroup parent) {if(convertView==null){tv=new TextView(QuerryUsualNumber.this);}else{tv=(TextView) convertView;}   tv.setTextSize(20);tv.setTextColor(Color.BLACK);tv.setText(" "+UsualNumberDao.getChildrenNameByPosition(db,groupPosition, childPosition));return tv;}@Overridepublic boolean isChildSelectable(int groupPosition,int childPosition) {return true;}
}
@Override
protected void onDestroy() {super.onDestroy();db.close();}

接口回调解耦的应用(用短信备份加进度条对话框来举例)

/*** 短信备份* * @param view*/
public void SMSBackUp(View view) {/*** 直接弹出一个进度条对话框*/final ProgressDialog pb = new ProgressDialog(this);pb.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);pb.setMessage("正在备份......");pb.show();// show出来才能看得见new Thread() {public void run() {boolean result = SMSTool.SmsBackup(new SMSTool.SmsBackupCallBack() {/*** 接口里面的方法*/@Overridepublic void callBackprogress(int progress) {pb.setProgress(progress);}/*** 接口里面的方法*/@Overridepublic void callBackMax(int max) {pb.setMax(max);}}, ToolActivity.this, "back.xml");if (result) {ToastUtils.show(ToolActivity.this, "备份成功");} else {ToastUtils.show(ToolActivity.this, "备份失败");}pb.dismiss();// 是否备份成功对话框都消失};}.start();}

短信备份的逻辑:

    /*** 短信备份的工具类* * @author Administrator* */
public class SMSTool {/*** 接口回调,定义一些抽象方法* * @author Administrator* */
public interface SmsBackupCallBack {/*** 接口回调* * @param max  最大值*           */public abstract void callBackMax(int max);/*** 接口回调* * @param progress*/public abstract void callBackprogress(int progress);}/*** 短信备份的业务逻辑* * @param context   上下文*          * @param filename 存进的文件名*            * @return*/
public static boolean SmsBackup(SmsBackupCallBack callBack,Context context, String filename) {try {ContentResolver resolver = context.getContentResolver();Uri uri = Uri.parse("content://sms/");Cursor cursor = resolver.query(uri, new String[] { "address","date", "body", "type" }, null, null, null);File file = new File(Environment.getExternalStorageDirectory(),filename);FileOutputStream fos = new FileOutputStream(file);XmlSerializer serialer = Xml.newSerializer();// 设置序列化参数serialer.setOutput(fos, "utf-8");serialer.startDocument("utf-8", true);serialer.startTag(null, "info");cursor.moveToNext();int max = cursor.getCount();int progress = 0;//接口方法callBack.callBackMax(max);while (cursor.moveToNext()) {// cursor.moveToNext();serialer.startTag(null, "sms");serialer.startTag(null, "address");String address = cursor.getString(0);serialer.text(address);serialer.endTag(null, "address");serialer.startTag(null, "date");String date = cursor.getString(1);serialer.text(date);serialer.endTag(null, "date");serialer.startTag(null, "body");String body = cursor.getString(2);serialer.text(body);serialer.endTag(null, "body");serialer.startTag(null, "type");String type = cursor.getString(3);serialer.text(type);serialer.endTag(null, "type");serialer.endTag(null, "sms");progress++;//接口的方法callBack.callBackprogress(progress);}cursor.close();serialer.startTag(null, "info");serialer.endDocument();return true;} catch (Exception e) {e.printStackTrace();return false;}}
}

短信备份常见错误

  • org.kxml2.io.KXmlSerializer.text(KXmlSerializer.java:536)

这是因为短信的内容中存在着搜狗输入法的一些表情,无法识别,只要把带有表情符号的短信删除掉就可以成功备份

  • java.io.FileNotFoundException:
    /storage/emulated/0/backup.xml: 07-22 10:56:50.440: W/System.err(305): at
    open failed: EACCES (Permission denied)

    没有权限齐全,短信的读写,sd卡、内存卡的读写权限等

listview的优化:四大原则

1、时间换空间

(牺牲时间换取空间,流的读写)

2、空间换时间

(把文件的路径存进数据库,以后查询就快很多,Android下的图库应用检索)

3、时间换时间

(开机启动速度的优化)

4、空间换空间

把内存换成硬盘,或者把硬盘换成内存

获取手机中所有应用程序的关键信息以List

返回List集合对象

    public class AppManagerInfos {@SuppressWarnings("unused")public static List<AppInfo> getAppManagerInfos(Context context) {List<AppInfo> appinfos = new ArrayList<AppInfo>();PackageManager pm = context.getPackageManager();
//获取安装在手机上的应用程序List<PackageInfo> infos = pm.getInstalledPackages(0);for (PackageInfo appInfo : infos) {AppInfo info = new AppInfo();// 获得包名String packagename = appInfo.packageName;info.setPakageName(packagename);// 获得应用名称String appname = appInfo.applicationInfo.loadLabel(pm).toString();info.setAppname(appname);// 获得应用图标Drawable icon = appInfo.applicationInfo.loadIcon(pm);info.setIcon(icon);// 获得应用app的绝对路径String path = appInfo.applicationInfo.sourceDir;info.setPath(path);// 获得应用app的大小File file = new File(path);long size = file.length();String sizedata = Formatter.formatFileSize(context, size);info.setSize(size);int flag = appInfo.applicationInfo.flags;if ((flag & ApplicationInfo.FLAG_SYSTEM) == 0) {// 用户应用info.setUserapp(true);} else {// 系统应用info.setUserapp(false);}if ((flag & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0) {// 存在手机内存info.setInRom(true);} else {// 存在sd内存卡info.setInRom(false);}appinfos.add(info);}return appinfos;}
}

把不同集合数据展示到ListView中

    public class AppManagerActivity extends Activity {private TextView tv_shji_byte;
private TextView tv_sd_byte;
private ListView lv_listview;
private LinearLayout ll_loading;
private List<AppInfo> infos;
private List<AppInfo> userapp;
private List<AppInfo> systemapp;
private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {lv_listview.setAdapter(new MyAppManagerAdapter());ll_loading.setVisibility(View.INVISIBLE);};
};@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_app_manager);tv_shji_byte = (TextView) findViewById(R.id.tv_shji_byte);tv_sd_byte = (TextView) findViewById(R.id.tv_sd_byte);lv_listview = (ListView) findViewById(R.id.lv_listview);ll_loading = (LinearLayout) findViewById(R.id.ll_loading);userapp = new ArrayList<AppInfo>();systemapp = new ArrayList<AppInfo>();File datafile = Environment.getDataDirectory();long datasize = datafile.getFreeSpace();File sdfile = Environment.getExternalStorageDirectory();long sdsize = sdfile.getFreeSpace();tv_shji_byte.setText("手机可用内存"+ Formatter.formatFileSize(this, datasize));tv_sd_byte.setText("sd卡可用内存" + Formatter.formatFileSize(this, sdsize));fillData();}
/*** 填充数据*/
private void fillData() {new Thread() {public void run() {infos = AppManagerInfos.getAppManagerInfos(AppManagerActivity.this);for (AppInfo info : infos) {if (info.isUserapp()) {// 用户程序userapp.add(info);} else {systemapp.add(info);// 系统程序}}handler.sendEmptyMessage(0);};}.start();
}
private class MyAppManagerAdapter extends BaseAdapter {@Overridepublic int getCount() {return userapp.size() + systemapp.size() + 2;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view;HoldView holder;if (convertView != null && convertView instanceof RelativeLayout) {view = convertView;holder = (HoldView) view.getTag();} else {holder = new HoldView();view = View.inflate(AppManagerActivity.this,R.layout.item_app_manager, null);holder.app_name = (TextView) view.findViewById(R.id.app_name);holder.app_location = (TextView) view.findViewById(R.id.app_location);holder.app_icon = (ImageView) view.findViewById(R.id.app_icom);holder.app_size = (TextView) view.findViewById(R.id.app_size);view.setTag(holder);}AppInfo info;if (position == 0) {// 显示textView用户程序TextView tv_user = new TextView(AppManagerActivity.this);tv_user.setTextSize(15);tv_user.setBackgroundColor(Color.GREEN);tv_user.setTextColor(Color.BLACK);tv_user.setText("用户程序" + userapp.size() + "个");return tv_user;} else if (position == userapp.size() + 1) {TextView tv_system = new TextView(AppManagerActivity.this);tv_system.setTextSize(15);tv_system.setBackgroundColor(Color.GREEN);tv_system.setTextColor(Color.BLACK);tv_system.setText("系统程序" + systemapp.size() + "个");return tv_system;} else if (position < userapp.size() + 1) {// 用户程序info = userapp.get(position - 1);} else {// 系统程序info = systemapp.get(position - 2 - userapp.size());}holder.app_name.setText(info.getAppname());holder.app_icon.setImageDrawable(info.getIcon());holder.app_size.setText(Formatter.formatFileSize(AppManagerActivity.this, info.getSize()) + "M");if (info.isInRom()) {holder.app_location.setText("手机内存");} else {holder.app_location.setText("sd卡储存");}return view;}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}private class HoldView {TextView app_name;TextView app_location;ImageView app_icon;TextView app_size;}
}

设置listview属性可使其快速滚动

     android:fastScrollEnabled="true"

在listview滚动时悬浮标识符

在帧布局中加入一个TextView<TextView android:id="@+id/tv_biaoshi"android:layout_width="match_parent"android:background="#00FF00"android:textColor="#000000"android:textSize="15sp"android:text="用户程序"android:layout_height="wrap_content"/>

不过设置属性时需要和之前区分系统用户时的属性相同,背景色、字体、大小,这样才可以重合

    TextView tv_biaoshi=(TextView) findViewById(R.id.tv_biaoshi);/*** 给listview注册一个滚动监听器*/lv_listview.setOnScrollListener(new OnScrollListener() {/*** 当状态发生改变时执行此方法*/@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {}/*** 当listview滚动时执行此方法*/@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {if(firstVisibleItem>userapp.size()){tv_biaoshi.setText("系统程序"+systemapp.size()+"个");}else{tv_biaoshi.setText("用户程序"+userapp.size()+"个");}}});

悬浮窗体的创建使用(轻量级的对话框,内存开销比对话框小,灵活)漂浮的容器,在activity上方

        //点击条目弹出悬浮窗体TextView convertView=new TextView(AppManagerActivity.this);convertView.setTextSize(15);convertView.setTextColor(Color.RED);convertView.setText(info.getPakageName());popupwindow = new PopupWindow(convertView, 300, 100);popupwindow.setBackgroundDrawable(new ColorDrawable(Color.GREEN));//获取点击的条目view对象到窗体的宽高(左上对齐)存在location中x、yint []location=new int[2];view.getLocationInWindow(location);popupwindow.showAtLocation(parent, Gravity.TOP+Gravity.LEFT, 80, location[1]);

不过一般都是自定义悬浮窗体

View convertView=View.inflate(getApplicationContext(), R.layout.item_app_popupwindow, null);

布局文件item.app.popupwindow.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/tip_bg"
android:orientation="horizontal" ><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:layout_marginTop="5dp"android:orientation="vertical" ><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:src="@drawable/my_user_exit" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="3dp"android:text="启动" />
</LinearLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:layout_marginTop="5dp"android:orientation="vertical" ><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:src="@drawable/delete" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="3dp"android:text="删除" />
</LinearLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:orientation="vertical" ><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/wx_share_friends" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="3dp"android:text="分享" />
</LinearLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:layout_marginTop="5dp"android:orientation="vertical" ><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:src="@drawable/datasafety_item_icon_config" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="3dp"android:text="信息" />
</LinearLayout>
保证窗体中只有一个悬浮窗体,每次弹出前执行判断;listview滚动时消失也执行此方法public void dismissPopupwindow() {if(popupwindow!=null&& popupwindow.isShowing()){popupwindow.dismiss();popupwindow=null;}

动画的播放原理

确定一个变化的函数:
根据这个函数 动态计算在某个时间应该显示什么画面Canvas Bitmap  要求界面的窗体必须有背景,所以悬浮窗体必须设置背景才能启动动画}

一键分享

        //发送纯文本Intent intent=new Intent();intent.setAction(Intent.ACTION_SEND);intent.addCategory("android.intent.category.DEFAULT");intent.setType("text/plain");//intent.setType("image/*");//图片//intent.setType("video/*");//音频、视频//intent.setType("*/*");//所有类型intent.putExtra(Intent.EXTRA_TEXT, "请使用这款软件");startActivity(intent);

一键卸载

动态注册广播接收者innerReceiver=new InnerUninstallAppReceiver();IntentFilter filter=new IntentFilter();filter.addAction(Intent.ACTION_PACKAGE_REMOVED);filter.addDataScheme("package");registerReceiver(innerReceiver, filter);/*** 卸载软件程序后需要更新数据注册一个广播接收者*/
private void uninstallapp() {if(info.isUserapp()){Intent intent=new Intent();intent.setAction(Intent.ACTION_DELETE);intent.setData(Uri.parse("package:"+info.getPakageName()));startActivity(intent);}else{ToastUtils.show(this, "应用程序需要root权限才能卸载");}
}
/*** 内部类,广播接收者,监听软件卸载的事件* @author Administrator**/
private class InnerUninstallAppReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {if(info.isUserapp()){userapp.remove(info);}else{systemapp.remove(info);}adapter.notifyDataSetChanged();}}

一键启动软件

/*** 打开软件的功能*/
public void openApp() {PackageManager pm=getPackageManager();Intent intent=pm.getLaunchIntentForPackage(info.getPakageName());if(intent!=null){startActivity(intent);}else{ToastUtils.show(this, "软件无法启动!");}}

查看应用程序信息(也可卸载应用程序:系统的设置卸载界面)

    /*** 查看应用程序全部信息*/
private void showApp() {//查找上层应用程序源码/* <action android:name="android.settings.APPLICATION_DETAILS_SETTINGS" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="package" />*/Intent intent =new Intent();intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");intent.addCategory("android.intent.category.DEFAULT" );intent.setData(Uri.parse("package:"+info.getPakageName()));startActivity(intent);}

获取手机所有正在运行的进程(返回的是List集合)

package com.cca.mobilephone.engine;
import java.util.ArrayList;
import java.util.List;import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;import com.cca.mobilephone.domain.ProcessInfo;/*** 获取所有正在运行的进程信息* @author Administrator**/
public class TaskInfoProvifer {public static List<ProcessInfo> getRunningProcessInfo(Context context){List<ProcessInfo> process=new ArrayList<ProcessInfo>();ActivityManager am=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);PackageManager pm=context.getPackageManager();//获取正在运行的进程集合List<RunningAppProcessInfo>processrunninginfoinfo=am.getRunningAppProcesses();//遍历集合for(RunningAppProcessInfo runninginfo:processrunninginfoinfo){ProcessInfo processinfo=new ProcessInfo();//进程包名String packageName=runninginfo.processName;processinfo.setPackageName(packageName);long menSize=am.getProcessMemoryInfo(new int[]{runninginfo.pid})[0].getTotalPrivateDirty()*1024;processinfo.setMenSize(menSize);try {PackageInfo packageinfo=pm.getPackageInfo(packageName, 0);//进程图标Drawable icon=packageinfo.applicationInfo.loadIcon(pm);processinfo.setIcon(icon);//进程名称String processName=packageinfo.applicationInfo.loadLabel(pm).toString();processinfo.setProcessName(processName);//if((packageinfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)!=0){//系统进程processinfo.setUserProcess(false);}else{//用户进程processinfo.setUserProcess(true);}} catch (NameNotFoundException e) {e.printStackTrace();}process.add(processinfo);}return process;
}}

javabean类的信息

package com.cca.mobilephone.domain;
import android.graphics.drawable.Drawable;/*** 进程包含的信息* @author Administrator**/
public class ProcessInfo {private String packageName;
private String processName;
private Drawable icon;
private long menSize;
private boolean userProcess;
public String getPackageName() {return packageName;
}
public void setPackageName(String packageName) {this.packageName = packageName;
}
public String getProcessName() {return processName;
}
public void setProcessName(String processName) {this.processName = processName;
}
public Drawable getIcon() {return icon;
}
public void setIcon(Drawable icon) {this.icon = icon;
}
public long getMenSize() {return menSize;
}
public void setMenSize(long menSize) {this.menSize = menSize;
}
public boolean isUserProcess() {return userProcess;
}
public void setUserProcess(boolean userProcess) {this.userProcess = userProcess;
}

}

区分用户进程和系统进程(这是耗时操作)

List<ProcessInfo> processinfo=TaskInfoProvifer.getRunningProcessInfo(getApplicationContext());userprocess=new ArrayList<ProcessInfo>();systemprocess=new ArrayList<ProcessInfo>();for(ProcessInfo process:processinfo){if(process.isUserProcess()){//用户程序userprocess.add(process);}else{//系统程序systemprocess.add(process);}}//通知界面更新handler.sendEmptyMessage(0);

打开一个服务,内部注册一个广播接收者,监听锁屏清理进程

public class AutoKillService extends Service {private InnerScrrenOffReceiver receiver;private Timer timer;private TimerTask task;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();receiver=new InnerScrrenOffReceiver();IntentFilter filter=new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_OFF);registerReceiver(receiver, filter);/*** 常用定时器,可设置为定时清理的功能*/timer=new Timer();task=new TimerTask() {@Overridepublic void run() {//System.out.println("每1秒执行一次");//清理的逻辑}};timer.schedule(task,0, 1000);}@Overridepublic void onDestroy() {super.onDestroy();timer.cancel();task.cancel();unregisterReceiver(receiver);receiver=null;}private class InnerScrrenOffReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {//System.out.println("哈哈,屏幕锁屏了");ActivityManager am=(ActivityManager) getSystemService(ACTIVITY_SERVICE);List<RunningAppProcessInfo> infos=  am.getRunningAppProcesses();for(RunningAppProcessInfo info:infos){//杀死后台进程am.killBackgroundProcesses(info.processName);}}}
}

如何创建一个widget只需要3步

1、定义一个广播接收者继承AppwidgetProvider

2、在清单文件中配置广播接收者

<receiver android:name="ExampleAppWidgetProvider" >
<intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"android:resource="@xml/example_appwidget_info" />
</receiver>

3、建立一个xml文件夹存放资源example_appwidget_info.xml

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="294dp"
android:minHeight="72dp"
android:updatePeriodMillis="86400000"  //一天更新,最少半小时
android:previewImage="@drawable/preview"
android:initialLayout="@layout/example_appwidget">
</appwidget-provider>

4、自定义布局example_appwidget的内容

生命周期:

        在手机桌面上创建第一个widget 11-05 00:46:24.817: I/System.out(1687): onreceive 接收到了系统的广播消息11-05 00:46:24.817: I/System.out(1687): onenable   (适合应用程序widget的初始化.)11-05 00:46:24.817: I/System.out(1687): onreceive 接收到了系统的广播消息11-05 00:46:24.817: I/System.out(1687): onupdate (只要有新的widget被创建都会调用onupdate方法)11-05 00:46:27.347: I/System.out(1687): onreceive 接收到了系统的广播消息如果界面上已经有一个widget被创建,再创建相同的widget11-05 00:47:34.728: I/System.out(1687): onreceive 接收到了系统的广播消息11-05 00:47:34.728: I/System.out(1687): onupdate11-05 00:47:36.629: I/System.out(1687): onreceive 接收到了系统的广播消息删除一个widget11-05 00:48:48.019: I/System.out(1687): onreceive 接收到了系统的广播消息11-05 00:48:48.019: I/System.out(1687): ondelete最后一个widget被删除11-05 00:49:25.710: I/System.out(1687): onreceive 接收到了系统的广播消息11-05 00:49:25.710: I/System.out(1687): ondelete11-05 00:49:25.710: I/System.out(1687): onreceive 接收到了系统的广播消息11-05 00:49:25.710: I/System.out(1687): ondisabled (适合做应用程序扫尾的操作,)

总结: 不要记生命周期调用的先后顺序.

    onenable 方法什么时候调用ondisabled 方法什么时候调用onupdate方法 在每次创建新的widget的时候都会调用 , 并且当时间片到的时候也会调用

创建widget模板

public class MyWidget extends AppWidgetProvider {@Override
public void onReceive(Context context, Intent intent) {//创建第一个桌面widget的时候调用super.onReceive(context, intent);
}//每次创建widget时都会调用
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {Intent intent=new Intent(context,UpdateWidgetService.class);context.startService(intent);super.onUpdate(context, appWidgetManager, appWidgetIds);
}
//删除widget会调用
@Override
public void onDeleted(Context context, int[] appWidgetIds) {super.onDeleted(context, appWidgetIds);
}
//对widget做初始化时调用
@Override
public void onEnabled(Context context) {super.onEnabled(context);
}
//结束widget是调用,做扫尾工作
@Override
public void onDisabled(Context context) {super.onDisabled(context);Intent intent=new Intent(context,UpdateWidgetService.class);context.stopService(intent);
}
}

桌面启动服务定时更新widget

public class UpdateWidgetService extends Service {private Timer timer;
private TimerTask task;
@Override
public IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn null;
}
@Override
public void onCreate() {super.onCreate();timer=new Timer();task=new TimerTask(){@Overridepublic void run() {System.out.println("更新widget里面的内容");/** 进程间通讯*/ComponentName provider=new ComponentName(getApplicationContext(), MyWidget.class);/** 告诉桌面布局文件去哪里找*/RemoteViews views=new RemoteViews(getPackageName(), R.layout.process_widget);views.setTextViewText(R.id.process_count, "正在运行的软件"+ProcessInfoUtils.getRunningProcessCount(getApplicationContext())+"个");String availstr=Formatter.formatFileSize(getApplicationContext(), ProcessInfoUtils.getAvialRam(getApplicationContext()));views.setTextViewText(R.id.process_memory, "可用内存:"+availstr);am.updateAppWidget(provider, views);}};timer.schedule(task, 0, 5000);
}
@Override
public void onDestroy() {super.onDestroy();timer.cancel();task.cancel();timer=null;task=null;
}}

逆向小助手的使用:反编译获取素材资源文件,everything可快速查找

反编译 拖拽到目录

多层显示的帧布局,功能多多

<FrameLayoutandroid:layout_width="match_parent"android:layout_weight="1"android:layout_height="0dp" ><ListViewandroid:fastScrollEnabled="true"android:id="@+id/lv_process_listview"android:layout_width="match_parent"android:layout_height="match_parent" ></ListView><LinearLayoutandroid:id="@+id/ll_loading"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"android:visibility="visible" ><ProgressBarandroid:layout_width="wrap_content"android:layout_height="wrap_content" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="正在加载中..." /></LinearLayout><TextView android:id="@+id/tv_process_biaoshi"android:layout_width="match_parent"android:background="#00FF00"android:textColor="#000000"android:textSize="15sp"android:text="用户进程"android:layout_height="wrap_content"/>
</FrameLayout>

杀死所有运行的进程

    ActivityManager am=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);List<RunningAppProcessInfo> infos=am.getRunningAppProcesses();for(RunningAppProcessInfo info:infos){am.killBackgroundProcesses(info.processName);//参数为包名}

抽屉控件

(重下往上拉),也可指定拉升的高度

  <SlidingDrawerandroid:layout_width="match_parent"android:layout_height="match_parent"android:content="@+id/my_content"android:handle="@+id/my_handle" ><ImageViewandroid:id="@id/my_handle" //相当于把柄,,id必须使用父类的android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/ic_launcher" /><LinearLayout android:id="@id/my_content" //里面的内容,,id必须使用父类的android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"android:gravity="center"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="我是一个" /><ProgressBar android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout>
</SlidingDrawer>

也可重右往左拉

      <SlidingDrawerandroid:orientation="horizontal" //增加水平属性android:layout_width="match_parent"android:layout_height="match_parent"android:content="@+id/my_content"android:handle="@+id/my_handle" >

界面的切换(一个切面不同的布局切换)

    <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:orientation="horizontal" ><TextViewandroid:id="@+id/app_unlock"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tab_left_pressed"android:gravity="center_vertical"android:text="未加锁软件"android:textSize="20sp" /><TextViewandroid:id="@+id/app_locked"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tab_right_default"android:gravity="center_vertical"android:text="已加锁软件"android:textSize="20sp" /></LinearLayout><FrameLayoutandroid:layout_width="match_parent"android:layout_height="match_parent" ><LinearLayoutandroid:id="@+id/ll_loading"android:visibility="visible"android:layout_gravity="center"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical" ><ProgressBarandroid:layout_gravity="center"android:layout_width="wrap_content"android:layout_height="wrap_content" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="正在加载数据..." /></LinearLayout><LinearLayoutandroid:id="@+id/ll_appunlock"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" ><TextViewandroid:id="@+id/tv_unlock_count"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="未加锁软件" /><ListViewandroid:id="@+id/lv_unlock"android:layout_width="match_parent"android:layout_height="match_parent" ></ListView></LinearLayout><LinearLayoutandroid:id="@+id/ll_applocked"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="gone" ><TextViewandroid:id="@+id/tv_locked_count"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="加锁软件" /><ListViewandroid:id="@+id/lv_locked"android:layout_width="match_parent"android:layout_height="match_parent" ></ListView></LinearLayout></FrameLayout></LinearLayout>

主活动中点击切换

    package com.cca.mobilephone.activity;import java.util.ArrayList;
import java.util.List;import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.TranslateAnimation;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;import com.cca.mobilephone.R;
import com.cca.mobilephone.db.dao.AppClockDao;
import com.cca.mobilephone.domain.AppInfo;
import com.cca.mobilephone.engine.AppManagerInfos;
/*** 设置程序加锁的Activity* @author Administrator**/
public class AppLockedActivity extends Activity implements OnClickListener {private TextView app_unlock;
private TextView app_locked;
/*** 两种线性布局*/
private LinearLayout ll_applocked;
private LinearLayout ll_appunlock;
/*** 两种listview*/
private ListView lv_locked;
private ListView lv_unlock;
/*** 正在加载的进度条*/
private LinearLayout ll_loading;
/*** 所有程序的集合*/
private List<AppInfo> infos;
/*** 显示未加锁程序的个数*/
private TextView tv_unlock_count;
/*** 显示加锁程序的个数*/
private TextView tv_locked_count;
/*** 加锁的数据库*/
private AppClockDao dao;
/*** 加锁集合*/
private List<AppInfo> lockedInfo;
/*** 未加锁集合*/
private List<AppInfo> unlockInfo;
/*** 未加锁*/
private MylockAdapter unlockadapter;
/*** 加锁适配器*/
private MylockAdapter lockedadapter;private Handler handler=new Handler(){public void handleMessage(android.os.Message msg) {// 加载未加锁的适配器lv_unlock.setAdapter(unlockadapter);// 加载加锁的适配器lv_locked.setAdapter(lockedadapter);ll_loading.setVisibility(View.INVISIBLE);};
};@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_applocked);tv_unlock_count = (TextView) findViewById(R.id.tv_unlock_count);tv_locked_count = (TextView) findViewById(R.id.tv_locked_count);ll_loading=(LinearLayout) findViewById(R.id.ll_loading);dao = new AppClockDao(this);app_unlock = (TextView) findViewById(R.id.app_unlock);app_locked = (TextView) findViewById(R.id.app_locked);// 两种listviewlv_locked = (ListView) findViewById(R.id.lv_locked);lv_unlock = (ListView) findViewById(R.id.lv_unlock);// 两个不同点击事件app_locked.setOnClickListener(this);app_unlock.setOnClickListener(this);// 两个线性布局ll_applocked = (LinearLayout) findViewById(R.id.ll_applocked);ll_appunlock = (LinearLayout) findViewById(R.id.ll_appunlock);lockedInfo = new ArrayList<AppInfo>();unlockInfo = new ArrayList<AppInfo>();unlockadapter = new MylockAdapter(true);lockedadapter = new MylockAdapter(false);new Thread(){public void run() {// 获得全部软件程序infos = AppManagerInfos.getAppManagerInfos(getApplicationContext());/*** 遍历集合,区分加锁和未加锁*/for (AppInfo info : infos) {if (dao.find(info.getPakageName())) {lockedInfo.add(info);} else {unlockInfo.add(info);}}handler.sendEmptyMessage(0);};}.start();}@Override
public void onClick(View v) {switch (v.getId()) {case R.id.app_unlock:// 点击未加锁ll_appunlock.setVisibility(View.VISIBLE);ll_applocked.setVisibility(View.GONE);app_unlock.setBackgroundResource(R.drawable.tab_left_pressed);app_locked.setBackgroundResource(R.drawable.tab_left_default);break;case R.id.app_locked:// 点击已加锁ll_appunlock.setVisibility(View.GONE);ll_applocked.setVisibility(View.VISIBLE);app_unlock.setBackgroundResource(R.drawable.tab_left_default);app_locked.setBackgroundResource(R.drawable.tab_left_pressed);break;}
}
private class MylockAdapter extends BaseAdapter {/*** isunlock是否加锁的标识符 true 为未加锁 、 false 已加锁*/boolean isunlock;public MylockAdapter(boolean isunlock) {this.isunlock = isunlock;}@Overridepublic int getCount() {int count = 0;if (isunlock) {count = unlockInfo.size();tv_unlock_count.setText("未加锁软件:" + count);} else {count = lockedInfo.size();tv_locked_count.setText("加锁软件:" + count);}return count;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {final View view;ViewHolder holder;if (convertView != null && convertView instanceof RelativeLayout) {view = convertView;holder = (ViewHolder) view.getTag();} else {view = View.inflate(getApplicationContext(),R.layout.item_unlock_app, null);holder = new ViewHolder();holder.img_appicom = (ImageView) view.findViewById(R.id.img_appicom);holder.tv_appname = (TextView) view.findViewById(R.id.tv_appname);holder.img_locked = (ImageView) view.findViewById(R.id.img_locked);view.setTag(holder);}final AppInfo info;if (isunlock) {info = unlockInfo.get(position);holder.img_locked.setImageResource(R.drawable.list_button_lock_pressed);} else {info = lockedInfo.get(position);holder.img_locked.setImageResource(R.drawable.list_button_unlock_pressed);}holder.img_appicom.setImageDrawable(info.getIcon());holder.tv_appname.setText(info.getAppname());/*** 点击加锁按钮移出条目,把数据加到数据库*/holder.img_locked.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if (isunlock) {TranslateAnimation am = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);     am.setDuration(500);view.startAnimation(am);am.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {// 未加锁unlockInfo.remove(info);lockedInfo.add(info);dao.insert(info.getPakageName());// 通知界面更新// notifyDataSetChanged();unlockadapter.notifyDataSetChanged();lockedadapter.notifyDataSetChanged();}});} else {TranslateAnimation am = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);     am.setDuration(500);view.startAnimation(am);am.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {// 已经加锁lockedInfo.remove(info);unlockInfo.add(info);dao.delete(info.getPakageName());// 通知界面更新// notifyDataSetChanged();unlockadapter.notifyDataSetChanged();lockedadapter.notifyDataSetChanged();}});}}});return view;}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}
}static class ViewHolder {TextView tv_appname;ImageView img_appicom;ImageView img_locked;
}

}

在Service中开启一个活动Activity 在Activity往Service中发送信息采用自定义广播,只有服务才能接收:

活动中:

    Intent intent=new Intent();intent.setAction("com.cca.mobilesafe.watchdog");intent.putExtra("packageNmae",packageName);sendBroadcast(intent);

在服务中定义一个内部类广播接收者

private class InnerWatchDogReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {temppackageName = intent.getStringExtra("packageName");}
}

在onCreate方法中注册广播接收者:

    //注册一个广播接收者receiver=new InnerWatchDogReceiver();IntentFilter filter=new IntentFilter();filter.addAction("com.cca.mobilephone.watchdog");registerReceiver(receiver, filter);

程序锁的主逻辑

package com.cca.mobilephone.service;
import java.util.List;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;import com.cca.mobilephone.activity.EnterPasswordActivity;
import com.cca.mobilephone.db.dao.AppClockDao;
/*** 看门狗服务,监视运行的软件* @author Administrator**/
public class WatchDogLockService extends Service {private ActivityManager am;private boolean flags;private AppClockDao dao;private InnerWatchDogReceiver receiver;
/*** 临时不需要保护的包名*/private String temppackageName;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();//注册一个广播接收者receiver=new InnerWatchDogReceiver();IntentFilter filter=new IntentFilter();filter.addAction("com.cca.mobilephone.watchdog");registerReceiver(receiver, filter);//获取活动管理器am=(ActivityManager) getSystemService(ACTIVITY_SERVICE);flags=true;dao=new AppClockDao(this);new Thread(){public void run() {while(flags){//获取任务站里面的情况,对于任务栈里面的信息进行排序,最近使用的排在最前面List<RunningTaskInfo> infos = am.getRunningTasks(100);String packageName=infos.get(0).topActivity.getPackageName();if(dao.find(packageName)){//程序需要被保护,弹出一个输入密码的对话框//再次判断是否需要保护if(packageName.equals(temppackageName)){//暂时不需要保护}else{//需要保护Intent intent =new Intent(getApplicationContext(),EnterPasswordActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.putExtra("packageName", packageName);startActivity(intent);}}else{//程序不需要被保护}try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}};}.start();}@Overridepublic void onDestroy() {super.onDestroy();flags=false;unregisterReceiver(receiver);receiver=null;}/*** 定义内部类广播接收者,接收不需要保护的程序包名* @author Administrator**/private class InnerWatchDogReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {temppackageName = intent.getStringExtra("packageName");}}
}

程序的优化:考虑每个细节执行的时间,可以优化就优化

当有手机卫士在后台运行时,界面的跳转就不正常了,需要为打开密码保护的程序Activity设置一个模式:打开运用时会在一个新的任务栈中运行,这样就不会跳转回手机卫士了

       android:launchMode="singleInstance"

在低版本时运行还没弹出密码界面就已经进入程序界面了,可以看到一些信息了,需要优化代码,执行效率更快

List<RunningTaskInfo> infos = am.getRunningTasks(100);

这句代码我们只需要获取第一个运用程序的包名

List<RunningTaskInfo> infos = am.getRunningTasks(1)定义为;

并定义为成员变量

优化:查询数据库所消耗的时间比内存中的多,把数据库查询的数据放在内存中,需要使用时到内存中查找即可

优化程序后发现新增加的要保护的程序保护不了,想到数据库查询时已经把数据存储在内存中固定了,所以要重新查询即更新数据,可以使用广播接收者、也可以使用内容观察者来观察数据库的变化,增加和删除一旦发现,重新查询数据存进内存中。

优化后的代码:电量的优化 屏幕锁屏后和锁屏的广播接收者

    /*** 看门狗服务,监视运行的软件* @author Administrator**/
public class WatchDogLockService extends Service {private ActivityManager am;private boolean flags;private AppClockDao dao;private InnerWatchDogReceiver receiver;private List<RunningTaskInfo> infos ;private String packageName;
/*** 临时不需要保护的包名*/private String temppackageName;/*** 内容观察者*/private AppClockDaoObserver observer;private Intent intent;private List<String> packname;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();//注册一个广播接收者receiver=new InnerWatchDogReceiver();IntentFilter filter=new IntentFilter();filter.addAction("com.cca.mobilephone.watchdog");filter.addAction(Intent.ACTION_SCREEN_OFF);filter.addAction(Intent.ACTION_SCREEN_ON);registerReceiver(receiver, filter);intent = new Intent(getApplicationContext(),EnterPasswordActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//获取活动管理器am=(ActivityManager) getSystemService(ACTIVITY_SERVICE);dao=new AppClockDao(this);packname = dao.findAll();//注册一个内容观察者Uri uri=Uri.parse("content://com.cca.mobilephone.appclockdb");observer=new AppClockDaoObserver(new Handler());getContentResolver().registerContentObserver(uri, true, observer);showWhatchDogStart();}/**对电量的优化,锁屏后停止监控**/public void showWhatchDogStart() {if(flags==false){return ;}flags=true;new Thread(){public void run() {while(flags){//获取任务站里面的情况,对于任务栈里面的信息进行排序,最近使用的排在最前面infos= am.getRunningTasks(1);packageName=infos.get(0).topActivity.getPackageName();if(packname.contains(packageName)){//程序需要被保护,弹出一个输入密码的对话框//再次判断是否需要保护if(packageName.equals(temppackageName)){//暂时不需要保护}else{//需要保护intent.putExtra("packageName", packageName);startActivity(intent);}}else{//程序不需要被保护}try {Thread.sleep(30);} catch (InterruptedException e) {e.printStackTrace();}}};}.start();}@Overridepublic void onDestroy() {super.onDestroy();flags=false;unregisterReceiver(receiver);receiver=null;}/*** 定义内部类广播接收者* @author Administrator**/private class InnerWatchDogReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {if("com.cca.mobilephone.watchdog".equals(intent.getAction())){temppackageName = intent.getStringExtra("packageName");}else if(Intent.ACTION_SCREEN_OFF.equals(intent.getAction())){//屏幕锁屏temppackageName=null;flags=false;}else if(Intent.ACTION_SCREEN_ON.equals(intent.getAction())){//屏幕解锁showWhatchDogStart();}}}/*** 定义内容观察者内部类* @author Administrator**/private class AppClockDaoObserver extends ContentObserver{public AppClockDaoObserver(Handler handler) {super(handler);}//观察到数据库内容发生变化@Overridepublic void onChange(boolean selfChange) {super.onChange(selfChange);System.out.println("内容观察者观察到数据库发生变化了");packname = dao.findAll();}}
}

内容观察者

数据库中大声发个消息

Uri uri=Uri.parse("content://com.cca.mobilesafe.applockdb");
context.getContentResolver().notifyChange(Uri,null);

注册一个内容观察者:

    Uri uri=Uri.parse("content://com.cca.mobilesafe.applockdb");observer=new ApplockDBObserver(new Handler());getContentResolver().registerContentObserver(uri,true,observer);

定义一个内容观察者内部类

    /*** 定义内容观察者内部类* @author Administrator**/
private class AppClockDaoObserver extends ContentObserver{public AppClockDaoObserver(Handler handler) {super(handler);}//观察到数据库内容发生变化@Overridepublic void onChange(boolean selfChange) {super.onChange(selfChange);packname = dao.findAll();}
}

目录

getFilesDir();  //data/data/<包名>/files 文件目录
getCacheDir();  //data/data/<包名>/cache 缓存目录

扫描手机获取所有程序员的缓存

public class CleanCacheActivity extends Activity {protected static final int SCAN_STOP = 1;public static final int SEND_SCAN = 2;private ProgressBar pb;private TextView tv_scan_cache;private FrameLayout fl_scan_states;private PackageManager pm;private ListView lv_scan_listview;private List<CacheHolder>cache;private MyAdapter adapter;/*** 消息机制*/private Handler handler=new Handler(){public void handleMessage(android.os.Message msg) {switch(msg.what){case SCAN_STOP://扫描结束Toast.makeText(getApplicationContext(), "扫描完毕", 0).show();fl_scan_states.setVisibility(View.GONE);if(cache.size()>0){//设置适配器adapter=new MyAdapter();lv_scan_listview.setAdapter(adapter);}else{ToastUtils.show(CleanCacheActivity.this, "恭喜你,你的手机100分");}break;case SEND_SCAN://正在扫描String appname=(String) msg.obj;tv_scan_cache.setText("正在清理:"+appname);break;}};};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_clean_cache);//初始化数据pb=(ProgressBar) findViewById(R.id.pb);tv_scan_cache=(TextView) findViewById(R.id.tv_scan_cache);fl_scan_states=(FrameLayout) findViewById(R.id.fl_scan_states);lv_scan_listview=(ListView) findViewById(R.id.lv_scan_listview);pm=getPackageManager();//扫描缓存scanCache();}/*** 扫描手机应用分别获取缓存信息*/private void scanCache() {fl_scan_states.setVisibility(View.VISIBLE);cache=new ArrayList<CacheHolder>();//开子线程扫描程序缓存new Thread(){public void run() {pb.setMax(100);int progress=0;//1、扫描应用程序全部的包名List<PackageInfo>infos=pm.getInstalledPackages(0);for(PackageInfo info:infos){try {//获取每个程序的包名String packagename=info.packageName;//利用反射获取指定的方法名Method method=PackageManager.class.getMethod("getPackageSizeInfo", String.class,IPackageStatsObserver.class);method.invoke(pm,packagename,new MyObserver());} catch (Exception e) {e.printStackTrace();}//进度条的设置progress++;pb.setProgress(progress);try {sleep(50);} catch (InterruptedException e) {e.printStackTrace();}}//2、通知界面更新Message msg=Message.obtain();msg.what=SCAN_STOP;handler.sendMessage(msg);};}.start();
}
private class MyObserver extends IPackageStatsObserver.Stub{@Overridepublic void onGetStatsCompleted(PackageStats pStats, boolean succeeded)throws RemoteException {try {//把扫描到的包名发送回主界面更新Message  msg=Message.obtain();msg.what=SEND_SCAN;String appname=pm.getPackageInfo(pStats.packageName, 0).applicationInfo.loadLabel(pm).toString();msg.obj=appname;handler.sendMessage(msg);//主有有缓存大小的程序才需要存进集合中if(pStats.cacheSize>0){CacheHolder holder=new CacheHolder();holder. cachesize=pStats.cacheSize;//缓存大小holder. packName=pStats.packageName;//代码大小holder. icon=pm.getPackageInfo(holder. packName, 0).applicationInfo.loadIcon(pm);holder. appName=appname;cache.add(holder);}} catch (Exception e) {e.printStackTrace();}}
}private class CacheHolder{long cachesize;String packName;Drawable icon;String appName;
}
/*** listview的适配器* @author Administrator**/
private class MyAdapter extends BaseAdapter{@Overridepublic int getCount() {return cache.size();}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view;ViewHolder holder;//服用历史缓存对象,优化listviewif(convertView!=null){view=convertView;holder=(ViewHolder) view.getTag();}else{holder=new ViewHolder();view=View.inflate(getApplicationContext(), R.layout.item_cache_listview, null);holder.icon=(ImageView) view.findViewById(R.id.img_icon);holder.apname=(TextView) view.findViewById(R.id.tv_appname);holder.cachesize=(TextView) view.findViewById(R.id.tv_cachesize);holder.clearcache=(ImageView) view.findViewById(R.id.img_clear_button);view.setTag(holder);}final CacheHolder cacheholder=cache.get(position);holder.icon.setImageDrawable(cacheholder.icon);holder.apname.setText(cacheholder.appName);holder.cachesize.setText("缓存大小"+Formatter.formatFileSize(getApplicationContext(), cacheholder.cachesize));holder.clearcache.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {//打开应用程序信息Intent intent =new Intent();intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");intent.addCategory("android.intent.category.DEFAULT" );intent.setData(Uri.parse("package:"+cacheholder.packName));startActivity(intent);}});if(cacheholder.cachesize==0){cache.remove(cacheholder);adapter.notifyDataSetChanged();}return view;}
}
private class ViewHolder{ImageView icon;TextView apname;TextView cachesize;ImageView clearcache;
}class ClearCacheObserver extends IPackageDataObserver.Stub {public void onRemoveCompleted(final String packageName, final boolean succeeded) {ToastUtils.show(CleanCacheActivity.this, "清除状态"+succeeded);}}/*** 清理全部的缓存空间* @param view*/public void AllClearCache(View view){Method[] methods=PackageManager.class.getMethods();for(Method method:methods){if("freeStorageAndNotify".equals(method.getName())){try {method.invoke(pm, Long.MAX_VALUE*1024,new ClearCacheObserver());} catch (Exception e) {e.printStackTrace();}scanCache();return ;}}}
}

自定义进度条

在drawable下建立一个progress_horizontal.xml

<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android">//整个进度条背景<item android:id="@android:id/background" android:drawable="@drawable/security_progress_bg"></item><item android:id="@android:id/secondaryProgress" android:drawable="@drawable/security_progress">//缓存到的背景</item><item android:id="@android:id/progress" android:drawable="@drawable/security_progress">//当前背景</item></layer-list>

设置进度条的属性引用它

  android:progressDrawable="@drawable/progress_horizontal"

这样就自定义好了进度条

具体的配置也可配置一下节点

share.xml下

在share节点下

android:shape="rectangle"  //圆角矩形
<corners android:radius="5dp"/> //弧度
<gradient //渐变色android:startColor="#ff0000"android: endColor="#22ffff00"/>
<padding //边距android:left="5dp"android:right="5dp"android:top="5dp"android:bottom="5dp"
/>
<solid android:width="1dp" android:color="#0000ff"/>  //固定颜色不可和渐变色一起使用<stroke android:width="1dp" android:color="#000000"
//实线        android:dashWidth="5dp" android:dashGap="2dip" //虚线/>

清理缓存

    //打开应用程序信息,手动清除Intent intent =new Intent();intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");intent.addCategory("android.intent.category.DEFAULT" );intent.setData(Uri.parse("package:"+cacheholder.packName));startActivity(intent);

全部清理缓存

/*** 清理全部的缓存空间* @param view*/public void AllClearCache(View view){Method[] methods=PackageManager.class.getMethods();for(Method method:methods){if("freeStorageAndNotify".equals(method.getName())){try {method.invoke(pm, Long.MAX_VALUE*1024,new ClearCacheObserver());} catch (Exception e) {e.printStackTrace();}scanCache();return ;}}}

手机杀毒的方式

1、最原始的查杀方式

基于文件的的特征码(缺点:只能查杀已知的病毒,不能查杀未知的病毒)

2、基于程序的行为去查杀(主动防御)

替换系统的API(看雪论坛)

3、人工智能(学习模式+数据库)

字符串与字符串之间的距离

手机杀毒的实现

数据库的实现:

    package com.cca.mobilephone.db.dao;import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
/*** 病毒数据库* @author Administrator**/
public class AntiVriusDao {/*** 在数据库中查找程序特征码是否存在,存在就是病毒软件,不存在就不是* @param md5* @return*/public static String isVriusdb(String md5){SQLiteDatabase db=SQLiteDatabase.openDatabase("/data/data/com.cca.mobilephone/files/antivirus.db",null, SQLiteDatabase.OPEN_READONLY);Cursor cursor=db.rawQuery("select desc from datable where md5=?", new String[]{md5});String desc=null;if(cursor.moveToNext()){desc=cursor.getString(0);}db.close();cursor.close();return desc;}
}

ui布局·:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="3dp"android:orientation="horizontal" ><FrameLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content" ><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/ic_scanner_malware" /><ImageViewandroid:id="@+id/img_rotate"android:layout_width="60dp"android:layout_height="60dp"android:layout_gravity="center"android:src="@drawable/act_scanning_03" /></FrameLayout><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center" ><TextViewandroid:id="@+id/tv_now_querry"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="6dp"android:gravity="center_horizontal"android:text="正在查杀..." /><ProgressBarandroid:id="@+id/verits_pb"style="?android:attr/progressBarStyleHorizontal"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@id/tv_now_querry"android:layout_marginLeft="15dp"android:layout_marginRight="15dp"android:layout_marginTop="4dp"android:progressDrawable="@drawable/progress_horizontal" /></RelativeLayout></LinearLayout><LinearLayoutandroid:id="@+id/ll_add_text"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"></LinearLayout></LinearLayout>

代码的实现:

public class AntiVirusActivity extends Activity {private ImageView img_rotate;private LinearLayout ll_add_text;private ProgressBar verits_pb;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_antivures);img_rotate=(ImageView) findViewById(R.id.img_rotate);ll_add_text=(LinearLayout) findViewById(R.id.ll_add_text);verits_pb=(ProgressBar) findViewById(R.id.verits_pb);/** 旋转动画*/RotateAnimation ra=new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);ra.setDuration(2000);ra.setRepeatCount(Animation.INFINITE);img_rotate.startAnimation(ra);//扫描手机应用程序scanVirus();}/*** 扫描手机应用程序,查找手机病毒程序*/private void scanVirus() {/*** 遍历手机应用程序的信息,查询他的特征码在病毒数据库中是否存在*/PackageManager pm=getPackageManager();List<PackageInfo> pakageinfos=pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);verits_pb.setMax(pakageinfos.size());int progress=0;for(PackageInfo info:pakageinfos){try {String apkpath=info.applicationInfo.sourceDir;File file=new File(apkpath);MessageDigest digest=MessageDigest.getInstance("md5");FileInputStream fis=new FileInputStream(file);byte[] buffer=new byte[1024];int len=0;while((len=fis.read(buffer))!=-1){digest.update(buffer, 0, len);}byte [] result=digest.digest();StringBuffer sb=new StringBuffer();for(byte b:result){String str=Integer.toHexString(b&0xff);if(str.length()==1){sb.append("0");}sb.append(str);}progress++;verits_pb.setProgress(progress);String md5=sb.toString();/*** 查找md5是否存在病毒数据库中*/final String desc=AntiVriusDao.isVriusdb(md5);final String appname=(String) info.applicationInfo.loadLabel(pm);runOnUiThread(new Runnable() {@Overridepublic void run() {TextView tv=new TextView(AntiVirusActivity.this);if(desc!=null){//发现病毒tv.setTextColor(Color.RED);tv.setText(appname+":发现病毒");}else{//扫描安全tv.setTextColor(Color.GREEN);tv.setText(appname+":扫描安全");}ll_add_text.addView(tv, 0);}});Thread.sleep(50);} catch (Exception e) {e.printStackTrace();}}}
}

隐藏应用程序的图标(不被用户发觉)

getPackageManager().setComponentEnabledSetting(getComponentName(),PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP);

围绕中心轴旋转

    /** 旋转动画*/RotateAnimation ra=new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);ra.setDuration(2000);ra.setRepeatCount(Animation.INFINITE);img_rotate.startAnimation(ra);

程序的签名

/*** 获取应用程序的签名信息、使用MD5加密,要加上标志位PackageManager.GET_SIGNATURES ,系统默认不解析 TODO*/
System.out.println("程序名"+info.applicationInfo.loadLabel(pm));
System.out.println("签名:"+MD5Utils.encode(info.signatures[0].toCharsString()));

获取程序的校验码

    /*** 获取程序的校验码*///apk的路径String apkpath=info.applicationInfo.sourceDir;File file=new File(apkpath);MessageDigest digest=MessageDigest.getInstance("md5"); //这里使用MD5 也可以使用  "sha-1"  获取FileInputStream fis=new FileInputStream(file);byte[] buffer=new byte[1024];int len=0;while((len=fis.read(buffer))!=-1){digest.update(buffer, 0, len);}byte [] result=digest.digest();StringBuffer sb=new StringBuffer();for(byte b:result){String str=Integer.toHexString(b&0xff);if(str.length()==1){sb.append("0");}sb.append(str);}

创建应用程序的图标

    /***创建快捷图标*/
private void createShortCut() {SharedPreferences sp=getSharedPreferences("config", MODE_PRIVATE);boolean shortcut=sp.getBoolean("shortcut", false);if(!shortcut){//快捷方式的图片//快捷方式的名称//快捷方式干什么事情//快捷图标其实是显示在桌面的,让桌面帮我们创建快捷图标//给桌面发送消息Intent intent=new Intent(); //发送广播的意图intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");//设置数据intent.putExtra(Intent.EXTRA_SHORTCUT_NAME,"破荒卫士" );intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));//快捷方式开启对应的意图Intent shortcutIntent=new Intent();shortcutIntent.setAction("com.cca.mobilesafe.home");shortcutIntent.addCategory(Intent.CATEGORY_DEFAULT);intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);//发送创建快捷方式的广播sendBroadcast(intent);Editor edit=sp.edit();edit.putBoolean("shortcut", true);edit.commit();}}

消息的通知

//消息的通知、先下兼容低版本
private void createNotification() {//获取通知管理者NotificationManager nm=(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);Notification notification=new Notification(R.drawable.ic_launcher, "破荒手机卫士正在保护你的手机!", System.currentTimeMillis());//设置通知的标志notification.flags=Notification.FLAG_NO_CLEAR;//意图打开主界面Intent intent=new Intent();intent.setAction("com.cca.mobilesafe.home");intent.addCategory(Intent.CATEGORY_DEFAULT);PendingIntent contentIntent= PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);notification.setLatestEventInfo(this, "破荒手机卫士", "正在保护你的手机", contentIntent);nm.notify(0, notification);}

对应用程序中的Log的控制,想打印什么类型的信息只要修改LOGLEVEL的值

package com.cca.mobilephone.Utils;import android.util.Log;/*** 应用程序的Log的控制* @author Administrator**/
public class Logger {private static final int  VERBOSE=1;private static final int  DEBUG=2;private static final int  INFO=3;private static final int  WARN=4;private static final int  ERROR=5;private static  int  LOGLEVEL=4;public static void v(String tag,String msg){if(VERBOSE>LOGLEVEL){Log.v(tag, msg);}}public static void d(String tag,String msg){if(DEBUG>LOGLEVEL){Log.d(tag, msg);}}public static void i(String tag,String msg){if(INFO>LOGLEVEL){Log.i(tag, msg);}}public static void w(String tag,String msg){if(WARN>LOGLEVEL){Log.w(tag, msg);}}public static void e(String tag,String msg){if(ERROR>LOGLEVEL){Log.e(tag, msg);}}
}

应用程序的异常处理,捕获到异常信息存进指定的目录,可以上传至服务器中

package com.cca.mobilephone.log;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import android.app.Application;
import com.cca.mobilephone.Utils.Logger;
/*** 代表的就是当前手机卫士的应用程序* 《b》一定要注意在清单文件Application中配置,点Browser会自动匹配* @author Administrator**/
public class MobileSafeApplication extends Application {//开天地,老母子方法@Overridepublic void onCreate() {super.onCreate();Thread.currentThread().setUncaughtExceptionHandler(new MyExceptionHandler());}/*** 捕获异常信息存进sd中,再上传至服务器中* @author Administrator**/private class MyExceptionHandler implements UncaughtExceptionHandler{@Overridepublic void uncaughtException(Thread thread, Throwable ex) {Logger.i("","发生了异常,被哥捕获到了。。。。。");//并不能把异常消化掉,只是在应用程序挂掉之前,来一个留遗嘱的时间try {//获取手机适配的信息Field[] fields=Builder.class.getDeclaredFields();StringBuffer sb=new StringBuffer();for(Field field:fields){String value=field.get(null).toString();String name=field.getName();sb.append(value);sb.append(":");sb.append(name);sb.append("\n");}//输出异常信息FileOutputStream out=new FileOutputStream("/mnt/sdcard/error.log");//阻塞性方法,直接写到内存中,内存输出流StringWriter wr=new StringWriter();PrintWriter err=new PrintWriter(wr);//打印输出流,异步输出流ex.printStackTrace(err);String errorlog=wr.toString();out.write(errorlog.getBytes());out.flush();out.close();} catch (Exception e) {e.printStackTrace();}//ActivityManager 可以杀死别的进程,不能自杀,而专注于自杀是 android.os.Processandroid.os.Process.killProcess(android.os.Process.myPid());}}
}

应用程序的混淆加密(四大组件、自定义控件不可混淆)

操作方法:直接到目录把 sdk/tools/proguard/proguard-android这个文件拷贝到工程目录下就可以导出apk文件了

混淆工作原理:

全局替换 :类名、变量名、方法名

想把什么给保留出来,只要增加一下类似的语句

-keep class com.cca.mobilesafe.domain.AppInfo

介绍广告

1、内付费互联网公司
2、软件付费
3、免费软件+广告

cpm:千次有效展现
cpc:点击
cpa:完整有效点击
cpd:下载

广告主

代理公司(有米、百度联盟)

小程序员

常见系统的管理器:

  • TelephonyManager:电话管理的服务
  • SmsManager :信息的管理服务
  • DevicesManager :设备的超级管理者
  • ActivityManager:活动管理器:获取进程和服务的管理器,相当于window系统的任务管理器,获取的是动态信息
  • PackageManager:获取各种包的信息(版本、应用程序图标、包信息等)相当于window系统的软件管理,获取的是静态的信息
  • AppWidgetManager 桌面小控件
  • NotificationManager 通知的管理
  • LocationManager 位置提供者
  • WindowManager窗口管理者

Android之手机卫士涉及的知识点总结相关推荐

  1. Android核心基础(手机卫士的一个知识点总结)

    注意:有些功能是需要权限的,在这里并没有写出来,在程序运行中,根据程序报的错误,添加相应的权限即可,里面的具体里面可能有一些小细节,没有明确的写出来,具体的需要在程序中自己调试,解决. 这个总结涵盖了 ...

  2. Android 《手机卫士》随听笔记

    <手机卫士>随听笔记: 防止子控件抢占父控件焦点: android:descendantFocusability="blocksDescendants" 加layout ...

  3. Android--手机卫士涉及的知识点总结(六)

    内容观察者 数据库中大声发个消息 ? 1 2 Uri uri=Uri.parse( "content://com.cca.mobilesafe.applockdb" ); cont ...

  4. Android之手机卫士

    代码组织结构 根据业务逻辑划分 办公软件 出差 com.itheima.travel 工资 com.itheima.money 会议 com.itheima.meeting 网盘 上传 com.vdi ...

  5. Android--手机卫士涉及的知识点总结(一)

    Splash界面 splash: 溅,洒 展现产品的logo提升产品的知名度 初始化操作(创建 数据库 ,读取配置文件) 连接服务器检查软件授权 连接服务器检查软件的更新 自动更新的前提 包名一致 签 ...

  6. android 百度手机卫士 卸载,百度卫士卸载方法汇总

    很多用户比较习惯使用360杀毒软件,一些用户也下载安装使用百度卫士了,但总觉得没有360杀毒软件好用,安装有两个软件那肯定是非常不爽的.那要怎么卸载百度卫士呢?下面小编 介绍百度卫士卸载方法汇总. 方 ...

  7. 专访刘刚:360手机卫士的性能监控与优化

    作为一款移动端产品,除了要保证安全性之外,手机卫士还需要考虑尽量减少对手机资源的消耗,而要做到这些,360手机卫士对于自身的性能优化.性能监控,以及对不同产品的适配问题,有哪些改进之处值得我们借鉴呢? ...

  8. 【android】仿360手机卫士的简易设计思路及源码

    笔者最近一直忙于满广州的跑,实习好难找好难找,博客也是有点久没去更新.仿360手机卫士的实现的目的更多的是出于对常用知识点的一个巩固吧,比较适合像我这种接触没多久的学习者在学习之余拿来练手保持写代码的 ...

  9. android 360旋转动画,ANDROID——仿360手机卫士的旋转打分控件

    简介 灵感源自360手机卫,主要功能就是实现显示评分或等级的效果.并稍微改良了一下,有更好的实用性和扩展性. 因为主要用途就是显示"分数","评价",所以暂且叫 ...

最新文章

  1. 怎样借助Python爬虫给宝宝起个好名字
  2. Activity的四种启动模式和onNewIntent()
  3. 数据库索引的使用及优化
  4. CentOs上docker安装nginx、tomcat、redis
  5. 使用vue加svg实现流程图代码_snap.svg+vue实现圆形导航
  6. 计算机软考软件设计师2019试题,软考试题及答案【2018计算机软考软件设计师考前练习试题及答案】...
  7. JAVA共享图片管理系统毕业设计 开题报告.
  8. 宾馆管理系统(做了ppt忘记发博客了)
  9. 解析:为什么程序员应该有一台Mac个人电脑?
  10. 二保焊接中有送丝问题,怎么解决?
  11. html实现银行卡中间四位显示为*号,银行卡和手机号中隐藏的数字用*号代替,不能和文字垂直居中,有什么解决方案吗?...
  12. 什么是Civil3D
  13. 减少2021年度汇算清缴补税
  14. jetson nano运行darknet_ros的环境配置
  15. Caused by: liquibase.exception.ValidationFailedException: Validation Failed:1 change sets check sum
  16. 二分法中 mid=beg+(end-beg)/2 与 mid=(beg+end)/2 的区别?
  17. 优达(Udacity)-机器学习基础-数据集与问题(安然数据集)
  18. NBA球星库里入股FTX并担任品牌大使,后者此前已签下布雷迪
  19. HDU 5952 Counting Cliques(2016ACM/ICPC亚洲区沈阳站-重现赛)
  20. 对话昔日“斜杠青年”西蒙斯:传奇数学家的别样人生

热门文章

  1. AtCoder Beginner Contest 236 A-D题解
  2. LeetCode第9题 回文数(Palindrome Number)
  3. 【GNN报告】腾讯AI lab 徐挺洋:图生成模型及其在分子生成中的应用
  4. html网站设计基础
  5. 计算机论文结束语致谢,论文结束语和致谢
  6. 集群监控:Ambari和Cloudera Manger
  7. webpack优化系列七:首屏加载优化
  8. start.bat批处理文件
  9. oculusHome 无法登录提示显示错误 ovr....
  10. 可能是国内第一篇全面解读Java现状及趋势的文章