Android项目实战_手机安全卫士系统加速

## 1.本地数据库自动更新的工作机制
1. 开启一个服务,定时访问服务器
2. 进行版本对比,如果最新版本比较高,获取需要更新的内容
3. 将新内容插入到本地数据库中

## 2.如何处理横竖屏切换
1. 指定屏幕朝向
在清单文件对应的Activity中配置android:screenOrientation=”landscape”(横屏,portrait是竖屏);
2. 设置屏幕旋转时不重新创建Activity
在清单文件对应的Activity中配置android:configChanges="keyboardHidden|orientation|screenSize",最好这三个都配置,否则不能适配所有机型或sdk版本。
横竖屏切换时会走Activity的onConfigurationChanged()方法

@Override
public void onConfigurationChanged(Configuration newConfig) {
// 当新设置中,屏幕布局模式为横排时
if(newConfig.orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE){
//TODO 某些操作
}else{
//TODO 某些操作
}
super.onConfigurationChanged(newConfig);
}

##3.系统控件的样式在哪里定义
1. 找到文件:sdk/platforms/某个版本/data/res/values/styles.xml
2. 搜索关注的控件,如ProgressBar

<style name="Widget.ProgressBar.Horizontal">
//indeterminate不确定
<item name="android:indeterminateOnly">false</item>
//进度条使用的图片
<item name="android:progressDrawable">@android:drawable/progress_horizontal</item>
//进度不确定的时候使用的图片,如安装APK时系统的进度条
<item name="android:indeterminateDrawable">@android:drawable/progress_indeterminate_horizontal</item>
<item name="android:minHeight">20dip</item>
<item name="android:maxHeight">20dip</item>
</style>

##4.Fragment添加到Activity上有哪些步骤?
//获得管理器
FragmentManager fm = getSupportFragmentManager();

//获得切换Fragment的帮助类,有add添加、delete删除、replace替换、hide隐藏、show显示
FragmentTransaction ft = fm.beginTransaction();

//创建Fragment
CleanCacheFragment f1 = new CleanCacheFragment();
ft.replace(R.id.fl_container, f1);

//提交切换Fragment的事务
ft.commit();

##5.Fragment的生命周期
1. onAttach():Fragment对象跟Activity关联时

2. onCreate():Fragment对象的初始创建时

3. onCreateView():创建Fragment的View对象时

4. onActivityCreate():所依附的Activity对象已经完成了Activity.onCreate()方法时

5. onStart():界面即将显示给用户,当Activity的onStart方法调用时

6. onResume():可以获取焦点与用户交互,当Activity的onResume调用时

7. onPause():Activity被遮挡不可获取焦点调用了onPause时,或者Activity(或其他容器)打开另一个Fragment,当前Fragemnt无法获取焦点时

8. onStop():Activity不可见调用了onStop()时,或者Activity(或其他容器)打开另一个Fragment当前Fragment不再显示给用户时

9. onDestroyView():Fragment中的View对象即将被从当前界面中移除时

10. onDestroy():Fragment对象被销毁时

11. onDetach():在Fragment对象不再跟它依附的Activity关联的时候,方法会立即被调用

## 6.缓存
路径:data/data/包名/cache。用于存放临时文件,当系统空间不足时会清空该目录数据

//获取当前应用的缓存文件夹
context.getCacheDir();

## 7.如何从应用源码中定位实现逻辑
1. 通过UI上一些字符串进行全局搜索,Ctrl+H 中的 FileSearch
2. 通过string.xml中对应字符串id定位layout布局
3. 通过layout布局中的id,定位代码中该View的事件逻辑

## 8.如何获取应用的缓存
1. 经过分析源码,发现获取应用的缓存可以使用packageManager.getPackageSizeInfo()方法
2. pm的getPackageSizeInfo()方法为hide,无法直接调用,所以使用反射调用该方法
3. getPackageSizeInfo()需要两个参数,第一个为包名,第二个为一个回调接口IPackageStatsObserver.Stub这种形式一般为远程调用系统服务,需要使用aidl,将aidl文件拷贝到本项目中,注意要使用aidl文件中的原始包名
4. 代码实现,需要权限<uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/>

//1.获得packageManager对象
PackageManager pm = getPackageManager();

//2.pm的getPackageSizeInfo()方法为hide,使用反射调用
Method[] methods = PackageManager.class.getDeclaredMethods();
for(Method method:methods){
if("getPackageSizeInfo".equals(method.getName())){
try {

//3.第二个参数需要使用aidl创建
method.invoke(pm, "com.hb.testcache",new IPackageStatsObserver.Stub(){
@Override
public void onGetStatsCompleted(PackageStats pStats,
boolean succeeded) throws RemoteException {
long cacheSize = pStats.cacheSize;
System.out.println("缓存大小:"+cacheSize);
}
});
} catch (Exception e) {
e.printStackTrace();
}
return;
}
}

###界面实现步骤:

1. 在onstart方法中开启子线程获取每一个应用程序的包名,缓存大小,应用名等信息
2. 在扫描的过程中睡眠50毫秒去显示进度条的更新
3. 通过handler消息机制来更新textview文本显示正在扫描的应用程序
4. 扫描完毕更新ui显示有缓存的应用程序(Linearlayout添加多个textview实现)

注意:应用程序的包名,缓存大小,应用名等最好做成一个业务bean,方便数据传递和使用


## 9.如何清除一个应用的缓存
需要应用为系统应用

packageManager.deleteApplicationCacheFiles(String packageName,IPackageDataObserver observer)
权限:要求系统应用
<uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
只能通过打开应用详细信息界面,让用户手动去点击清除缓存

Intent intent = new Intent("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:"+info.packName));
startActivity(intent);

###10.清除全部应用缓存
利用系统漏洞,google忘记把CLEAR\_APP\_CACHE权限声明为只有系统应用才可以申请的权限

//建议Long.MAX_VALUE。
PackageManager.freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer);
//权限
<uses-permission android:name="android.permission.CLEAR_APP_CACHE" />

//模拟一个超级大存储空间的请求。
//freeStorageAndNotify
Method[] methods = PackageManager.class.getDeclaredMethods();
for(Method method:methods){
if("freeStorageAndNotify".equals(method.getName())){
try {
method.invoke(pm, Long.MAX_VALUE,new IPackageDataObserver.Stub() {
@Override
public void onRemoveCompleted(String packageName, boolean succeeded)
throws RemoteException {

}
});
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}

activity:

 1 package com.hb.mobilesafe.activities;
 2 
 3 import android.app.Activity;
 4 import android.app.FragmentManager;
 5 import android.app.FragmentTransaction;
 6 import android.os.Bundle;
 7 import android.view.View;
 8 import android.view.View.OnClickListener;
 9 import android.view.Window;
10 import android.widget.FrameLayout;
11 import android.widget.LinearLayout;
12 
13 import com.hb.demo_mobilesafe.R;
14 import com.hb.mobilesafe.fragmet.ChacheFramgment;
15 import com.hb.mobilesafe.fragmet.SdcardFramgment;
16 
17 public class SysChacheActivity extends Activity implements OnClickListener {
18     private FrameLayout fl_content;
19     private LinearLayout ll_clrea_chache;
20     private LinearLayout ll_clrean_sdcard;
21     
22     @Override
23     protected void onCreate(Bundle savedInstanceState) {
24         // TODO Auto-generated method stub
25         super.onCreate(savedInstanceState);
26         requestWindowFeature(Window.FEATURE_NO_TITLE);
27         setContentView(R.layout.activity_syschache);
28         ll_clrean_sdcard=(LinearLayout) findViewById(R.id.ll_clrean_sdcard);
29         ll_clrea_chache=(LinearLayout) findViewById(R.id.ll_clrea_chache);
30         fl_content=(FrameLayout) findViewById(R.id.fl_content);
31         ll_clrea_chache.setOnClickListener(this);
32         ll_clrean_sdcard.setOnClickListener(this);
33         FragmentManager fm = getFragmentManager();
34         FragmentTransaction ft = fm.beginTransaction();
35         ft.replace(R.id.fl_content,new ChacheFramgment(SysChacheActivity.this));
36         ft.commit();
37     }
38     @Override
39     public void onClick(View v) {
40         FragmentManager fm = getFragmentManager();
41         FragmentTransaction ft = fm.beginTransaction();
42         switch (v.getId()) {
43         case R.id.ll_clrea_chache:
44             ft.replace(R.id.fl_content,new ChacheFramgment(SysChacheActivity.this));
45             
46             break;
47         case R.id.ll_clrean_sdcard:
48             
49             ft.replace(R.id.fl_content, new SdcardFramgment(SysChacheActivity.this));
50             
51             break;
52         }
53         ft.commit();
54     }
55 
56 }

fragment:

  1 package com.hb.mobilesafe.fragmet;
  2 
  3 import java.lang.reflect.Method;
  4 import java.util.ArrayList;
  5 import java.util.List;
  6 
  7 import android.annotation.SuppressLint;
  8 import android.app.Fragment;
  9 import android.content.Context;
 10 import android.content.pm.IPackageDataObserver;
 11 import android.content.pm.IPackageStatsObserver;
 12 import android.content.pm.PackageInfo;
 13 import android.content.pm.PackageManager;
 14 import android.content.pm.PackageStats;
 15 import android.graphics.Color;
 16 import android.os.Bundle;
 17 import android.os.Handler;
 18 import android.os.Message;
 19 import android.os.RemoteException;
 20 import android.os.SystemClock;
 21 import android.text.format.Formatter;
 22 import android.view.LayoutInflater;
 23 import android.view.View;
 24 import android.view.View.OnClickListener;
 25 import android.view.ViewGroup;
 26 import android.widget.Button;
 27 import android.widget.LinearLayout;
 28 import android.widget.ProgressBar;
 29 import android.widget.TextView;
 30 
 31 import com.hb.demo_mobilesafe.R;
 32 import com.hb.mobilesafe.bean.AppChacheInfo;
 33 
 34 @SuppressLint("InflateParams") 
 35 public class ChacheFramgment extends Fragment {
 36 
 37 
 38     protected static final int CHACHE = 0;
 39     private static final int SIZE = 1;
 40     private TextView tv_show_name;
 41     private LinearLayout ll_show_content;
 42     private Button bt_clean;
 43     private Context context;
 44     private PackageManager pm;
 45     private ProgressBar pg_gram;
 46     public ChacheFramgment(Context context){
 47         this.context=context;
 48     }
 49     private Handler handler=new Handler(){
 50         public void handleMessage(android.os.Message msg) {
 51             switch (msg.what) {
 52             case 0:
 53                 tv_show_name.setText("扫描完成");
 54                 pg_gram.setVisibility(View.GONE);
 55                 break;
 56 
 57             case SIZE:
 58                 AppChacheInfo appinfo=(AppChacheInfo)msg.obj;
 59                 tv_show_name.setText("正在扫描:"+appinfo.getAppName());
 60                 TextView textView=new TextView(context);
 61                 textView.setTextColor(Color.RED);
 62                 if(appinfo.getAppChaCheSize()>0){
 63                     textView.setText(appinfo.getAppName()+":"+Formatter.formatFileSize(context, appinfo.getAppChaCheSize()));
 64                     ll_show_content.addView(textView, 0);
 65                 }
 66                 break;
 67             case 3:
 68                 tv_show_name.setText("清理完成");
 69                 ll_show_content.removeAllViews();
 70                 break;
 71             }
 72         };
 73     };
 74     @Override
 75     public View onCreateView(LayoutInflater inflater, ViewGroup container,
 76             Bundle savedInstanceState) {
 77         View view = inflater.inflate(R.layout.fagment_chache, null);
 78         tv_show_name = (TextView) view.findViewById(R.id.tv_show_name);
 79         ll_show_content = (LinearLayout) view.findViewById(R.id.ll_show_content);
 80         bt_clean=(Button) view.findViewById(R.id.bt_clean);
 81         pg_gram=(ProgressBar) view.findViewById(R.id.pB_program);
 82         bt_clean.setOnClickListener(new OnclikLeanEvent());
 83         pm = context.getPackageManager();
 84         return view;
 85     }
 86     @Override
 87     public void onStart() {
 88         super.onStart();
 89         new ThreadRun().start();
 90         
 91     }
 92     /**
 93      * 扫描所有APP
 94      * @return
 95      */
 96     public List<AppChacheInfo> scanApp(){
 97         List<PackageInfo> list = pm.getInstalledPackages(0);
 98         List<AppChacheInfo> aInfo=new ArrayList<AppChacheInfo>();
 99         for (PackageInfo mInfo : list) {
100             AppChacheInfo info = new AppChacheInfo();
101             String packageName = mInfo.packageName;
102             String appName = mInfo.applicationInfo.loadLabel(pm).toString();
103             info.setAppPacagenName(packageName);
104             info.setAppName(appName);
105             aInfo.add(info);
106         }
107         int i=0;
108         for (AppChacheInfo cInfo : aInfo) {
109             findChache(cInfo.getAppPacagenName(), cInfo);
110             i++;
111             pg_gram.setProgress(i);
112             SystemClock.sleep(200);
113             Message message=new Message();
114             message.obj=cInfo;
115             message.what=SIZE;
116             handler.sendMessage(message);
117         }
118         
119         return aInfo;
120 
121     }
122 
123     /**
124      * 得到缓存
125      * public abstract void getPackageSizeInfo(String packageName, int userHandle,
126      *      IPackageStatsObserver observer);
127      *Stub 存根,负责接收本地方法调用,并将它们赋给各自的具体实现对象
128      */
129 
130     public void findChache(String packageName ,final AppChacheInfo chacheInfo){
131         try {
132 
133             Method method = PackageManager.class.getMethod("getPackageSizeInfo",String.class, IPackageStatsObserver.class);
134             method.invoke(pm, packageName,new IPackageStatsObserver.Stub() {
135 
136                 @Override
137                 public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
138                         throws RemoteException {
139                     long size = pStats.cacheSize;
140                     chacheInfo.setAppChaCheSize(size);
141                 }
142             });
143         } catch (Exception e) {
144             e.printStackTrace();
145         }
146     }
147     /**
148      * 
149      * @author 清理缓存
150      * class ClearCacheObserver extends IPackageDataObserver.Stub {
151         public void onRemoveCompleted(final String packageName, final boolean succeeded) {
152             final Message msg = mHandler.obtainMessage(CLEAR_CACHE);
153             msg.arg1 = succeeded ? OP_SUCCESSFUL:OP_FAILED;
154             mHandler.sendMessage(msg);
155          }
156      }
157      */
158     private void clean()  {
159         try {
160             Method method = PackageManager.class.getMethod("freeStorageAndNotify", long.class,IPackageDataObserver.class);
161             method.invoke(pm,Long.MAX_VALUE,new IPackageDataObserver.Stub() {
162 
163                 @Override
164                 public void onRemoveCompleted(String packageName, boolean succeeded)
165                         throws RemoteException {
166                     handler.sendEmptyMessage(3);
167                 }
168             });
169         } catch (Exception e) {
170             // TODO Auto-generated catch block
171             e.printStackTrace();
172         }
173     }
174     class OnclikLeanEvent implements OnClickListener {
175 
176         @Override
177         public void onClick(View v) {
178             clean();
179         }
180 
181     }
182     @Override
183     public void onDestroy() {
184         super.onDestroy();
185         new ThreadRun().interrupt();
186         
187     }
188     class ThreadRun extends Thread{
189         @Override
190         public void run() {
191             super.run();
192             List<AppChacheInfo> app = scanApp();
193             pg_gram.setMax(app.size());
194             handler.sendEmptyMessage(0);
195         }
196     }
197     
198 
199 }

 

posted @ 2017-06-12 11:01  想今生得与失  阅读(368)  评论(0编辑  收藏  举报