1. 程式人生 > >Android項目實戰_手機安全衛士系統加速

Android項目實戰_手機安全衛士系統加速

存儲 abs andro ddc mat author empty ring send

## 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 }

Android項目實戰_手機安全衛士系統加速