Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 清楚程序緩存

Android 清楚程序緩存

編輯:關於Android編程

其實清除緩存是有兩種的,一種是清除手機rom裡面的緩存,一種是清除手機sd卡裡面的緩存,我們今天主要講的就是第一種

ps:這裡來一個知識掃盲,就是手機裡面的rom和ram啦,如果已經知道了的,就可以跳過啦,我們去買手機,有時候經常會被那些銷售人員忽悠的,說什麼8G的內存啦,什麼的,其實他這裡面說的極大可能就是你手機裡面rom的大小啦,rom就是read only menory(只讀存儲器)你可以把它當成你電腦上的硬盤,不過它只能讀取而已,ram就是random access menory(隨機存取器)這個就相當於你電腦的內存啦,所以那個銷售人員說的手機內存有多大的時候,我們一定要問清楚啦,不要被人蒙了


好啦,回歸正題,我們今天講的那個緩存是清除手機rom裡面的緩存,其實也是挺簡單的,只要知道了要怎麼做之後,至於那個清除sd卡裡面的緩存的話,這個我到時會給大家說一下是怎樣清理的,具體我就不寫了,好,先來看一下我們要做的效果

加載中... 加載中...


上的第一個圖就是我們把我們的應用的一些信息給讀取出來了,但那個界面不怎麼好看,大家可以自己優化一下,當我們點擊了要清理緩存的條目時,我們就會進入到系統設置裡面的一個界面,因為清理rom裡面的緩存是要root才行的,而我們沒有root,那麼就只要借助系統裡面的功能啦,到時我也會教大家怎樣root手機的

好啦,廢話不多說,我們直接進入代碼階段

首先,我們先新建一個model類用來存放緩存的信息

com.xiaobin.security.domain.CacheInfo

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 package com.xiaobin.security.domain; import android.graphics.drawable.Drawable; public class CacheInfo { private String name; private String packageName; private Drawable icon; //應用大小 private String codeSize; //數據大小 private String dataSize; //緩存大小 private String cacheSize; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPackageName() { return packageName; } public void setPackageName(String packageName) { this.packageName = packageName; } public Drawable getIcon() { return icon; } public void setIcon(Drawable icon) { this.icon = icon; } public String getCodeSize() { return codeSize; } public void setCodeSize(String codeSize) { this.codeSize = codeSize; } public String getDataSize() { return dataSize; } public void setDataSize(String dataSize) { this.dataSize = dataSize; } public String getCacheSize() { return cacheSize; } public void setCacheSize(String cacheSize) { this.cacheSize = cacheSize; } }
寫完model類之後呢,我們就要把我們的應用的信息讀取出來啦,比如讀取應用大小啊,緩存大小啊,數據大小啊,這幾個信息,

那麼,怎樣去讀取這些信息呢,其實PackageManagerj裡面有一個私有的方法的,叫getPackageSizeInfo,

所以現在思路清楚啦,我們就是要通過反射來調用這個方法,然後,getPackageSizeInfo這個方法要傳遞一個IPackageStatsObserver.Stub對象的,這個對象我們一看,就知道是一個AIDL的對象啦,所以,我們就要把相應的AIDL文件給放到src目錄下面啦,我們就是在它裡面拿到緩存大小,這 些數據的啦,

好啦,說得有點玄,直接上代碼更清晰

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 /** * 通過AIDL的方法來獲取到應用的緩存信息,getPackageSizeInfo是PackageManager裡面的一個私有方法來的 * 我們通過反射就可以調用到它的了,但是這個方法裡面會傳遞一個IPackageStatsObserver.Stub的對象 * 裡面就可能通過AIDL來獲取我們想要的信息了 * * 因為這樣的調用是異步的,所以當我們完成獲取完這些信息之後,我們就通過handler來發送一個消息 * 來通知我們的應用,通過getCacheInfos來獲取到我們的Vector * * 為什麼要用Vector呢,因為下面的方法是異步的,也就是有可能是多線程操作,所以我們就用了線程安全的Vector * * @param cacheInfo * @param position */ private void initDataSize(final CacheInfo cacheInfo, final int position) { try { Method method = PackageManager.class.getMethod( "getPackageSizeInfo", new Class[] { String.class, IPackageStatsObserver.class }); method.invoke(packageManager, new Object[] { cacheInfo.getPackageName(), new IPackageStatsObserver.Stub() { @Override public void onGetStatsCompleted( PackageStats pStats, boolean succeeded) throws RemoteException { System.out.println("onGetStatsCompleted" + position); long cacheSize = pStats.cacheSize; long codeSize = pStats.codeSize; long dataSize = pStats.dataSize; cacheInfo.setCacheSize(TextFormater .dataSizeFormat(cacheSize)); cacheInfo.setCodeSize(TextFormater .dataSizeFormat(codeSize)); cacheInfo.setDataSize(TextFormater .dataSizeFormat(dataSize)); cacheInfos.add(cacheInfo); if (position == (size - 1)) { // 當完全獲取完信息之後,發送一個成功的消息 // 1對應的就是CacheClearActivity裡面的FINISH handler.sendEmptyMessage(1); } } } }); } catch (Exception e) { e.printStackTrace(); } }
有一點是要注意的,獲取緩存大小這些信息的內部實現是異步的,所以我們用一個vector來存放信息,免得會出來一些特殊的情況


好啦,下面我們把完整的類粘出來,這個類寫得有點復雜,主要是因為獲取緩存大小這些信息的內部實現是異步的,我們要保證數據的正確性,所以可能就寫得有點難理解

大家如果看不懂這個類的話,就歡迎留言

com.xiaobin.security.engine.CacheInfoProvider

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 package com.xiaobin.security.engine; import java.lang.reflect.Method; import java.util.List; import java.util.Vector; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageStatsObserver; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageStats; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.RemoteException; import com.xiaobin.security.domain.CacheInfo; import com.xiaobin.security.utils.TextFormater; public class CacheInfoProvider { private Handler handler; private PackageManager packageManager; private Vector cacheInfos; private int size = 0; public CacheInfoProvider(Handler handler, Context context) { // 拿到一個包管理器 packageManager = context.getPackageManager(); this.handler = handler; cacheInfos = new Vector(); } public void initCacheInfos() { // 獲取到所有安裝了的應用程序的信息,包括那些卸載了的,但沒有清除數據的應用程序 List packageInfos = packageManager .getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES); size = packageInfos.size(); for (int i = 0; i < size; i++) { PackageInfo packageInfo = packageInfos.get(i); CacheInfo cacheInfo = new CacheInfo(); // 拿到包名 String packageName = packageInfo.packageName; cacheInfo.setPackageName(packageName); // 拿到應用程序的信息 ApplicationInfo applicationInfo = packageInfo.applicationInfo; // 拿到應用程序的程序名 String name = applicationInfo.loadLabel(packageManager).toString(); cacheInfo.setName(name); // 拿到應用程序的圖標 Drawable icon = applicationInfo.loadIcon(packageManager); cacheInfo.setIcon(icon); initDataSize(cacheInfo, i); } } /** * 通過AIDL的方法來獲取到應用的緩存信息,getPackageSizeInfo是PackageManager裡面的一個私有方法來的 * 我們通過反射就可以調用到它的了,但是這個方法裡面會傳遞一個IPackageStatsObserver.Stub的對象 * 裡面就可能通過AIDL來獲取我們想要的信息了 * * 因為這樣的調用是異步的,所以當我們完成獲取完這些信息之後,我們就通過handler來發送一個消息 * 來通知我們的應用,通過getCacheInfos來獲取到我們的Vector * * 為什麼要用Vector呢,因為下面的方法是異步的,也就是有可能是多線程操作,所以我們就用了線程安全的Vector * * @param cacheInfo * @param position */ private void initDataSize(final CacheInfo cacheInfo, final int position) { try { Method method = PackageManager.class.getMethod( "getPackageSizeInfo", new Class[] { String.class, IPackageStatsObserver.class }); method.invoke(packageManager, new Object[] { cacheInfo.getPackageName(), new IPackageStatsObserver.Stub() { @Override public void onGetStatsCompleted( PackageStats pStats, boolean succeeded) throws RemoteException { System.out.println("onGetStatsCompleted" + position); long cacheSize = pStats.cacheSize; long codeSize = pStats.codeSize; long dataSize = pStats.dataSize; cacheInfo.setCacheSize(TextFormater .dataSizeFormat(cacheSize)); cacheInfo.setCodeSize(TextFormater .dataSizeFormat(codeSize)); cacheInfo.setDataSize(TextFormater .dataSizeFormat(dataSize)); cacheInfos.add(cacheInfo); if (position == (size - 1)) { // 當完全獲取完信息之後,發送一個成功的消息 // 1對應的就是CacheClearActivity裡面的FINISH handler.sendEmptyMessage(1); } } } }); } catch (Exception e) { e.printStackTrace(); } } public Vector getCacheInfos() { return cacheInfos; } public void setCacheInfos(Vector cacheInfos) { this.cacheInfos = cacheInfos; } }
其實主要的思想是這們的,當完全獲取完所有應用的緩存大小這些信息的時候,我們就給activity發送一個消息,然後activity裡面的handler處理這個消息,然後就通過getCacheInfos這個方法,拿到所有已經填充好信息的CacheInfos對象的集合啦,這樣,我們就可以回到activity裡面填充數據啦


上面我已經說過了,如果我們要自己刪除rom的緩存的話,那就是要root權限的,但我們現在沒有,所以,我們就要通過系統設置裡面的一個功能來進行清除啦

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 /** * Android2.3打開settings裡面的那個應用的詳細界面 * 後來我又查了一個Android4.1的,也是這樣寫的,所有應該是2.3之後,都是這樣寫的了, * 但是這只是猜測,各位有空的可以去下載Android Settings的代碼看一下 * 這樣就可以做成多個版本的適配了 * * * * * */ /** * Android2.2打開settings裡面的那個應用的詳細界面 * 用這個版本來打開的話,就要加多一句把包名設置進去的 * intent.putExtra("pkg", packageName); * * * * * */ Intent intent = new Intent(); intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); intent.addCategory("android.intent.category.DEFAULT"); intent.setData(Uri.parse("package:" + cacheInfos.get(position).getPackageName())); startActivity(intent);
上面的注釋已經很詳細了,我就不多說啦


下面是完整的activity代碼,布局文件就不放啦,因為寫得太難看了

com.xiaobin.security.ui.CacheClearActivity

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 package com.xiaobin.security.ui; import java.util.Vector; import android.annotation.SuppressLint; import android.app.ListActivity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import com.xiaobin.security.R; import com.xiaobin.security.domain.CacheInfo; import com.xiaobin.security.engine.CacheInfoProvider; public class CacheClearActivity extends ListActivity { private static final int LOADING = 0; private static final int FINISH = 1; private CacheInfoProvider provider; private ListView lv_list; private LinearLayout ll_load; private Vector cacheInfos; @SuppressLint("HandlerLeak") private Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case LOADING: ll_load.setVisibility(View.VISIBLE); break; case FINISH: ll_load.setVisibility(View.INVISIBLE); // 當加載完成之後,就調用provider裡面的get方法, // 這樣就可以得到一個加載完成後的數據了 cacheInfos = provider.getCacheInfos(); lv_list.setAdapter(new CacheAdapter()); break; default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.cache_clear); provider = new CacheInfoProvider(handler, this); lv_list = getListView(); ll_load = (LinearLayout) findViewById(R.id.ll_cache_clear_load); lv_list.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { /** * Android2.3打開settings裡面的那個應用的詳細界面 * 後來我又查了一個Android4.1的,也是這樣寫的,所有應該是2.3之後,都是這樣寫的了, * 但是這只是猜測,各位有空的可以去下載Android Settings的代碼看一下 * 這樣就可以做成多個版本的適配了 * * * * * */ /** * Android2.2打開settings裡面的那個應用的詳細界面 * 用這個版本來打開的話,就要加多一句把包名設置進去的 * intent.putExtra("pkg", packageName); * * * * * */ Intent intent = new Intent(); intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); intent.addCategory("android.intent.category.DEFAULT"); intent.setData(Uri.parse("package:" + cacheInfos.get(position).getPackageName())); startActivity(intent); } }); loadData(); } private void loadData() { ll_load.setVisibility(View.VISIBLE); new Thread(new Runnable() { @Override public void run() { provider.initCacheInfos(); } }).start(); } // ======================================================================= private class CacheAdapter extends BaseAdapter { @Override public int getCount() { return cacheInfos.size(); } @Override public Object getItem(int position) { return cacheInfos.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; ViewHolder holder; CacheInfo info = cacheInfos.get(position); if (convertView == null) { view = View.inflate(CacheClearActivity.this, R.layout.cache_clear_item, null); holder = new ViewHolder(); holder.iv_icon = (ImageView) view .findViewById(R.id.iv_cache_icon); holder.tv_name = (TextView) view .findViewById(R.id.tv_cache_name); holder.tv_code = (TextView) view .findViewById(R.id.tv_cache_code); holder.tv_data = (TextView) view .findViewById(R.id.tv_cache_data); holder.tv_cache = (TextView) view .findViewById(R.id.tv_cache_cache); view.setTag(holder); } else { view = convertView; holder = (ViewHolder) view.getTag(); } holder.iv_icon.setImageDrawable(info.getIcon()); holder.tv_name.setText(info.getName()); holder.tv_code.setText("應用大小:" + info.getCodeSize()); holder.tv_data.setText("數據大小:" + info.getDataSize()); holder.tv_cache.setText("緩存大小:" + info.getCacheSize()); return view; } } private class ViewHolder { ImageView iv_icon; TextView tv_name; TextView tv_cache; TextView tv_code; TextView tv_data; } }
好啦,到這裡為止,我們的清除rom裡面的緩存,就已經是完成的啦,最後,我給大家說一下清除sd卡裡面的緩存是怎樣的

大家都知道,我們裝的大部分應用,都會有sd卡裡面建一個目錄,然後裝一些應用的信息的,而這些,就是這些應用對應存放緩存的目錄啦,

要清除sd卡裡面的緩存,其實就是要有一個數據庫啦,它專門收錄市面上一些常用的應用,在sd卡上建立的目錄名稱,然後再通過這個數據庫,然後對sd卡裡面的目錄清除的而已,這個方法是比較的麻煩的,還要有數據庫的支持才行,所以大家可以自己試試


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved