可扩展的ListView(ExpandableListView控件)
public class QuerryUsualNumber extends Activity {
private ExpandableListView exl_listview;
private SQLiteDatabase db;
private TextView tv;
private MyExpandableAdapter adapter;
@Override
protected 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() {
@Override
public 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{
/**
* 获取分组的个数
*/
@Override
public int getGroupCount() {
return UsualNumberDao.getGroupCount(db);
}
/**
* 获取每个分组的孩子的个数
*/
@Override
public int getChildrenCount(int groupPosition) {
return UsualNumberDao.getChildGroupCount(db,groupPosition);
}
@Override
public Object getGroup(int groupPosition) {
return null;
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return null;
}
@Override
public long getGroupId(int groupPosition) {
return 0;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return 0;
}
@Override
public boolean hasStableIds() {
return false;
}
/**
* 返回每个分组的view对象
*/
@Override
public 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;
}
@Override
public 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;
}
@Override
public 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() {
/**
* 接口里面的方法
*/
@Override
public void callBackprogress(int progress) {
pb.setProgress(progress);
}
/**
* 接口里面的方法
*/
@Override
public 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);
}
/**
* 短信备份的业务逻辑--------解析XML
*
* @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;
}
}
}
- 短信备份常见错误
1、 org.kxml2.io.KXmlSerializer.text(KXmlSerializer.java:536)
这是因为短信的内容中存在着搜狗输入法的一些表情,无法识别,只要把带有表情符号的短信删除掉就可以成功备份
2、 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 getAppManagerInfos(Context context) {
List appinfos = new ArrayList();
PackageManager pm = context.getPackageManager();
//获取安装在手机上的应用程序
List 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 infos;
private List userapp;
private List 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();
systemapp = new ArrayList();
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 {
@Override
public int getCount() {
return userapp.size() + systemapp.size() + 2;
}
@Override
public 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;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public 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 tv_biaoshi=(TextView) findViewById(R.id.tv_biaoshi);
/**
* 给listview注册一个滚动监听器
*/
lv_listview.setOnScrollListener(new OnScrollListener() {
/**
* 当状态发生改变时执行此方法
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
/**
* 当listview滚动时执行此方法
*/
@Override
public 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、y
int []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
保证窗体中只有一个悬浮窗体,每次弹出前执行判断;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{
@Override
public 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() {
//查找上层应用程序源码
/*
*/
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 getRunningProcessInfo(Context context){
List process=new ArrayList();
ActivityManager am=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
PackageManager pm=context.getPackageManager();
//获取正在运行的进程集合
Listprocessrunninginfoinfo=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=TaskInfoProvifer.getRunningProcessInfo(getApplicationContext());
userprocess=new ArrayList();
systemprocess=new ArrayList();
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;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public 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() {
@Override
public void run() {
//System.out.println("每1秒执行一次");
//清理的逻辑
}
};
timer.schedule(task,0, 1000);
}
@Override
public void onDestroy() {
super.onDestroy();
timer.cancel();
task.cancel();
unregisterReceiver(receiver);
receiver=null;
}
private class InnerScrrenOffReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//System.out.println("哈哈,屏幕锁屏了");
ActivityManager am=(ActivityManager) getSystemService(ACTIVITY_SERVICE);
List infos= am.getRunningAppProcesses();
for(RunningAppProcessInfo info:infos){
//杀死后台进程
am.killBackgroundProcesses(info.processName);
}
}
}
}
逆向小助手的使用:反编译获取素材资源文件,everything可快速查找
多层显示的帧布局,功能多多
杀死所有运行的进程
ActivityManager am=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List infos=am.getRunningAppProcesses();
for(RunningAppProcessInfo info:infos){
am.killBackgroundProcesses(info.processName);//参数为包名
}
抽屉控件
(重下往上拉),也可指定拉升的高度
也可重右往左拉
界面的切换(一个界面不同的布局切换)
在Service中开启一个活动Activity 在Activity往Service中发送信息采用自定义广播,只有服务才能接收:
活动中:
Intent intent=new Intent();
intent.setAction("com.cca.mobilesafe.watchdog");
intent.putExtra("packageNmae",packageName);
在服务中定义一个内部类广播接收者
private class InnerWatchDogReceiver extends BroadcastReceiver{
@Override
public 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);
内容观察者
数据库中大声发个消息
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);
}
//观察到数据库内容发生变化
@Override
public 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 Listcache;
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;
}
};
};
@Override
protected 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();
//开子线程扫描程序缓存
new Thread(){
public void run() {
pb.setMax(100);
int progress=0;
//1、扫描应用程序全部的包名
Listinfos=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{
@Override
public 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{
@Override
public int getCount() {
return cache.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
ViewHolder holder;
//服用历史缓存对象,优化listview
if(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() {
@Override
public 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
//整个进度条背景
-
-
//缓存到的背景
-
//当前背景
设置进度条的属性引用它
android:progressDrawable="@drawable/progress_horizontal"
这样就自定义好了进度条
具体的配置也可配置一下节点
share.xml下
在share节点下
android:shape="rectangle" //圆角矩形
//弧度
//固定颜色不可和渐变色一起使用
清理缓存
//打开应用程序信息,手动清除
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 ;
}
}
}
隐藏应用程序的图标(不被用户发觉)
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);
}
应用程序的混淆加密(四大组件、自定义控件不可混淆)
操作方法:直接到目录把 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窗口管理者