編輯:關於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;
}
}
那麼,怎樣去讀取這些信息呢,其實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();
}
}
好啦,下面我們把完整的類粘出來,這個類寫得有點復雜,主要是因為獲取緩存大小這些信息的內部實現是異步的,我們要保證數據的正確性,所以可能就寫得有點難理解
大家如果看不懂這個類的話,就歡迎留言
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;
}
}
上面我已經說過了,如果我們要自己刪除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;
}
}
大家都知道,我們裝的大部分應用,都會有sd卡裡面建一個目錄,然後裝一些應用的信息的,而這些,就是這些應用對應存放緩存的目錄啦,
要清除sd卡裡面的緩存,其實就是要有一個數據庫啦,它專門收錄市面上一些常用的應用,在sd卡上建立的目錄名稱,然後再通過這個數據庫,然後對sd卡裡面的目錄清除的而已,這個方法是比較的麻煩的,還要有數據庫的支持才行,所以大家可以自己試試
遇到一個問題:昨天模擬器工作還正常,今天eclipse就識別不了了。後來發現是360手機助手占用了5555端口造成的,我就納悶了,平時這個也不是自動啟動,今天就啟動了。廢
關於判斷手機是否已經root的方法。如果app有一些特殊功能需要root權限,則需要判斷是否root。比如一些市場下載完app後自動安裝。方法1:/***
一:簡介 systrace 是 Android4.1 引入的一套用於做性能分析的工具。 基於 Linux 內核的 ftrace 機制(用於跟蹤 Linux 內核的函數調用
ToDoList(定制ArrayAdapter) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/