zoukankan      html  css  js  c++  java
  • 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<cacheinfo> cacheInfos;
        private int size = 0;
     
        public CacheInfoProvider(Handler handler, Context context)
        {
            // 拿到一个包管理器
            packageManager = context.getPackageManager();
            this.handler = handler;
            cacheInfos = new Vector<cacheinfo>();
        }
     
        public void initCacheInfos()
        {
            // 获取到所有安装了的应用程序的信息,包括那些卸载了的,但没有清除数据的应用程序
            List<packageinfo> 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<cacheinfo> getCacheInfos()
        {
            return cacheInfos;
        }
     
        public void setCacheInfos(Vector<cacheinfo> cacheInfos)
        {
            this.cacheInfos = cacheInfos;
        }
     
    }
    </cacheinfo></cacheinfo></packageinfo></cacheinfo></cacheinfo>

    其实主要的思想是这们的,当完全获取完所有应用的缓存大小这些信息的时候,我们就给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的代码看一下
     * 这样就可以做成多个版本的适配了
     * <intent-filter>
     
     * <category android:name="android.intent.category.DEFAULT">
     * <data android:scheme="package">
     * </data></category></action></intent-filter>
     */
     
    /**
     * Android2.2打开settings里面的那个应用的详细界面
     * 用这个版本来打开的话,就要加多一句把包名设置进去的
     * intent.putExtra("pkg", packageName);
     * <intent-filter>
     
     * <category android:name="android.intent.category.DEFAULT">
     * <category android:name="android.intent.category.VOICE_LAUNCH">
     * </category></category></action></intent-filter>
     */
     
    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<cacheinfo> 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的代码看一下
                     * 这样就可以做成多个版本的适配了
                     * <intent-filter>
                     
                     * <category android:name="android.intent.category.DEFAULT">
                     * <data android:scheme="package">
                     * </data></category></action></intent-filter>
                     */
                     
                    /**
                     * Android2.2打开settings里面的那个应用的详细界面
                     * 用这个版本来打开的话,就要加多一句把包名设置进去的
                     * intent.putExtra("pkg", packageName);
                     * <intent-filter>
                     
                     * <category android:name="android.intent.category.DEFAULT">
                     * <category android:name="android.intent.category.VOICE_LAUNCH">
                     * </category></category></action></intent-filter>
                     */
                     
                    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;
     
        }
     
    }
    </cacheinfo>

    好啦,到这里为止,我们的清除rom里面的缓存,就已经是完成的啦,最后,我给大家说一下清除sd卡里面的缓存是怎样的

    大家都知道,我们装的大部分应用,都会有sd卡里面建一个目录,然后装一些应用的信息的,而这些,就是这些应用对应存放缓存的目录啦,

    要清除sd卡里面的缓存,其实就是要有一个数据库啦,它专门收录市面上一些常用的应用,在sd卡上建立的目录名称,然后再通过这个数据库,然后对sd卡里面的目录清除的而已,这个方法是比较的麻烦的,还要有数据库的支持才行,所以大家可以自己试试


  • 相关阅读:
    Atitit 编程语言编程方法的进化演进 sp  COP ,AOP ,SOP
    Atitit 2016年attilax事业成就表
    Atitit 知识管理的重要方法 数据来源,聚合,分类,备份,发布 搜索
    Atitit webservice发现机制 WS-Discovery标准的规范attilax总结
    Atitit 多元化战略 适合我们发展 的核心业务attilax总结
    Atitit HTTP 认证机制基本验证 (Basic Authentication) 和摘要验证 (Digest Authentication)attilax总结
    Atitit. 提升存储过程与编程语言的可读性解决方案v3 qc25.docx
    Atitit zxing二维码qr码识别解析
    Atitit Data Matrix dm码的原理与特点
    Atitit 常用二维码对比(QR、PDF417、DM、汉信码 Aztec code maxicode
  • 原文地址:https://www.cnblogs.com/lechance/p/4373297.html
Copyright © 2011-2022 走看看