如何实现手机缓存清理的功能
来源:互联网 发布:淘宝上怎么搜高仿手表 编辑:程序博客网 时间:2024/04/30 03:35
android手机上的杀毒软件或者是手机管家等类似应用都会有垃圾清理的功能, 那么清理的缓存文件是什么? 怎么去找出应用的缓存文件并将他们清理, 在这里我将介绍如何实现手机垃圾文件清理的功能。
- 缓存文件是什么,缓存文件的目录在那里?
我们知道方法:
getFilesDir() 的路径是 /data/data/包名/files/
getCacheDir()的路径是 /data/data/包名/cache/
缓存文件路径就是getCacheDir()的路径,在此路径下的文件为缓存文件,当系统内存不够,系统会去释放这个路径下的文件。
先看一下缓存清理demo的结果:
2 界面编写
(1)主界面包括一个title, 一个进度条,一个线性布局保存扫描结果(也可以是listview这里为了简便), 一个清理按钮
布局代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#999999" android:orientation="vertical" tools:context=".MainActivity" > <TextView android:layout_width="match_parent" android:layout_height="40dp" android:gravity="center" android:text="缓存清理" android:textColor="#ffffff" android:textSize="22sp" /> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <ProgressBar android:id="@+id/pb" style="@android:style/Widget.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/scan_state" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="扫描状态" android:textColor="#ffffff" /> </FrameLayout> <LinearLayout android:layout_weight="1000" android:id="@+id/ll_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="5dp" android:orientation="vertical" > </LinearLayout> <Button android:id="@+id/clear_caches" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone" android:text="一键清除"/></LinearLayout>
(2)扫描到的缓存item布局文件:
包含两个textview展示应用名称与缓存大小,一个view作为分割线
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/app_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:textSize="20sp" /> <TextView android:id="@+id/cache_size" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/app_name" android:textColor="#ffffff" android:textSize="16sp" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:layout_below="@id/cache_size" android:background="#88000000" /></RelativeLayout>
3 功能逻辑实现代码
public class MainActivity extends Activity implements OnClickListener{ private ProgressBar pb; //扫描进度条 private TextView scan_state; //显示扫描的状态 private LinearLayout ll_container; //保存显示扫描结果 private PackageManager pm; //包管理 private Button cleanCaches; //清理手机缓存 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pb = (ProgressBar) findViewById(R.id.pb); scan_state = (TextView) findViewById(R.id.scan_state); ll_container = (LinearLayout) findViewById(R.id.ll_container); cleanCaches = (Button) findViewById(R.id.clear_caches); cleanCaches.setOnClickListener(this); scanCaches(); } //扫描手机里面所有的应用程序的缓存 private void scanCaches() { pm = getPackageManager(); //因为扫描缓存需要时间,开启线程来扫描 new Thread(){ public void run() { Method getPackageSizeInfoMethod = null; //getPackageSizeInfo方法在sdk中隐藏了,使用反射机制来获取此方法 //1.先获取PackageManager提供的所有方法 Method[] methods = PackageManager.class.getMethods(); //2.遍历所有方法找到getPackageSizeInfo方法 for (Method method : methods) { if("getPackageSizeInfo".equals(method.getName())) { getPackageSizeInfoMethod = method; break; } } //获取所有安装的包信息 List<PackageInfo> packageInfos = pm.getInstalledPackages(0); //设置进度条大小 pb.setMax(packageInfos.size()); int progress = 0; //遍历所有包,获取缓存信息 for (PackageInfo info : packageInfos) { try { getPackageSizeInfoMethod.invoke(pm, info.packageName, new MyDataObserver()); //防止扫描过快 Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } progress++; pb.setProgress(progress); } //扫描完毕,更新显示文本内容 runOnUiThread(new Runnable() { @Override public void run() { scan_state.setText("扫描完毕..."); //扫描完成,显示清理按钮 cleanCaches.setVisibility(View.VISIBLE); } }); }; }.start(); } private class MyDataObserver extends IPackageStatsObserver.Stub { @Override public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException { final long cache = pStats.cacheSize; final String packname = pStats.packageName; final ApplicationInfo appInfo; try { appInfo = pm.getApplicationInfo(packname, 0); runOnUiThread(new Runnable() { @Override public void run() { scan_state.setText("正在扫描:" + appInfo.loadLabel(pm)); if (cache > 0) { View view = View.inflate(getApplicationContext(), R.layout.cache_info_layout, null); TextView tv_cache = (TextView) view.findViewById(R.id.cache_size); tv_cache.setText("缓存大小:" + Formatter.formatFileSize(getApplicationContext(), cache)); TextView tv_name = (TextView) view.findViewById(R.id.app_name); tv_name.setText(appInfo.loadLabel(pm)); ll_container.addView(view, 0); } } }); } catch (Exception e) { e.printStackTrace(); } } } private class MyPackDataObserver extends IPackageDataObserver.Stub { @Override public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), "缓存删除成功", Toast.LENGTH_SHORT).show(); ll_container.removeAllViews(); scan_state.setText("缓存清理成功"); } }); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.clear_caches: CleanAllCache(); break; default: break; } } //清除所有缓存 private void CleanAllCache() { Method[] methods = PackageManager.class.getMethods(); for (Method method : methods) { if("freeStorageAndNotify".equals(method.getName())) { try { method.invoke(pm, Integer.MAX_VALUE, new MyPackDataObserver()); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.getCause().printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return; } } }}
代码中的注释已经很详细,但是这里需要说明一下,关于freeStorageAndNotify等方法的获得是使用反射机制,因为这些方法在PackageManager中是隐藏的,我们通过获取所有的method然后通过名字匹配,获得方法再通过invoke方法去使用获得的方法。具体关于获得所有应用的缓存与清理缓存的步骤方法可以参考android系统源码中的setting模块。
当你copy上面代码到你的工程中,肯定会报错,因为IPackageStatsObserver.Stub和IPackageDataObserver.Stub找不到,因为这两个类是aidl,因为读取与清理缓存需要读取其他应用程序,需要进程间数据通信。
你需要下载IPackageDataObserver.aidl, IPackageStatsObserver.aidl和PackageStats.aidl这三个文件(可以下载demo的源码,源码中包含这三个文件),在你的工程中创建一个名为android.content.pm的package,将这三个文件copy到这个包下,如图:
然后它会自动在gen目录下生成对应的java文件:
这个时候上面的代码就不会出现错误了,关于aidl这里不去介绍,不懂大家可以google一下。
注意: 应用程序需要下面两个权限:
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/> <uses-permission android:name="android.permission.CLEAR_APP_CACHE"/>
将其加到清单文件AndroidManifest.xml中。
4 关于缓存清理的功能原理
缓存清理利用了android的一个bug, 调用freeStorageAndNotify的方法,向系统请求说需要一块很大的内存这里传入的值是Integer.MAX_VALUE, 系统内存不够会去自动去将应用的缓存清理来满足内存的请求, 这样就实现了缓存清理的功能。
至此实现了手机缓存清理的功能,如有任何疑问可以留言。
源码下载地址:
http://download.csdn.net/detail/lbcab/9517254
- 如何实现手机缓存清理的功能
- iOS开发-清理缓存功能的实现
- iOS开发-清理缓存功能的实现
- iOS开发-清理缓存功能的实现
- iOS开发-清理缓存功能的实现
- iOS开发-清理缓存功能的实现
- iOS开发-清理缓存功能的实现
- iOS开发-清理缓存功能的实现
- iOS开发-清理缓存功能的实现
- iOS开发 清理缓存功能的实现
- iOS开发-清理缓存功能的实现
- iOS开发-清理缓存功能的实现
- Android清理缓存功能实现
- 如何为DEDE增加清理以下缓存文件夹的功能
- 基于Swift3.0/OC的缓存清理功能的实现
- 如何清理weblogic的缓存
- 清理手机缓存
- 手机清理缓存文件
- codeforces466E 并查集+离线处理+dfs
- C语言将16进制的数转换为字符串的方法
- Etag 笔记
- C++拷贝构造函数的调用时机,如没有重载等号操作符,需重写使用深拷贝
- a simple stone game--k倍动态规划减法游戏
- 如何实现手机缓存清理的功能
- iOS中利用 runtime 一键改变字体
- oracle 存储过程循环执行update语句
- 手机游戏上线前的准备
- dropbear支持sftp-server
- 类别---category
- windows还原后,eclipse创建的jsp项目css和js失效的问题
- 移动开发必读书单
- js查询重复字符串