应用管理中显示我们的应用占用了超过一个G存储空间,今天定位这些文件都是些什么文件写了个Demo,用于测试app自身产生了哪些文件,并计算这些文件大小。实用于没有Root的手机。
private static long getFileSize(File f) throws Exception
{
ECMLog.i_ecm(CLASS_TAG, "getFileSize called,f:" + f);
long size = 0;
if (f.isDirectory()){
File flist[] = f.listFiles();
if (flist == null || flist.length == 0){
ECMLog.i_ecm(CLASS_TAG, "folder:" + f + " has no files");
size = 0;
}else {
for (int i = 0; i < flist.length; i++)
{
if (flist[i].isDirectory())
{
size = size + getFileSize(flist[i]);
}
else
{
size = size + flist[i].length();
ECMLog.i_ecm(CLASS_TAG, "folder:" + f + " file:" + flist[i].getName() + " size:" + flist[i].length()/1024 + "KB");
if (i == flist.length -1){
ECMLog.i_ecm(CLASS_TAG, "folder:" + f + " total size:" + size/1024 + "KB");
}
}
}
}
}else {
size = f.length();
ECMLog.i_ecm(CLASS_TAG, "not directory,file:" + f + " size:" + size/1024 + "KB");
}
return size;
}
public static long printAppFileSizeInfo(Context context){
ECMLog.i_ecm(CLASS_TAG, "printAppFileSizeInfo called...");
String path=context.getPackageResourcePath();
ECMLog.i_ecm(CLASS_TAG, "PackageResourcePath:" + path);
File file = new File(path);
File resourceParentFolder = file.getParentFile();
ECMLog.i_ecm(CLASS_TAG, "resourceParentPath:" + resourceParentFolder);
long totalSize = 0;
long tmpSize = 0;
try {
tmpSize = getFileSize(resourceParentFolder);
totalSize += tmpSize;
ECMLog.i_ecm(CLASS_TAG, "PackageResource size:" + tmpSize);
} catch (Exception e) {
e.printStackTrace();
}
//返回:根据android版本,返回/data/data/packagename/files,或者/data/user/0/com.cetcs.ecmapplication/files
file = context.getFilesDir();
ECMLog.i_ecm(CLASS_TAG, "file:" + file);
if (file != null){
file = file.getParentFile();
try {
tmpSize = getFileSize(file);
ECMLog.i_ecm(CLASS_TAG, "data/data size:" + tmpSize);
totalSize += tmpSize;
} catch (Exception e) {
e.printStackTrace();
}
}
//返回:/storage/emulated/0/Android/data/com.cetcs.ecmapplication/files
file = context.getExternalFilesDir(null);
if (file != null){
file = file.getParentFile();
ECMLog.i_ecm(CLASS_TAG, "file:" + file);
try {
tmpSize = getFileSize(file);
ECMLog.i_ecm(CLASS_TAG, "External size:" + tmpSize);
totalSize += tmpSize;
} catch (Exception e) {
e.printStackTrace();
}
}
ECMLog.i_ecm(CLASS_TAG, "total size:" + totalSize);
return totalSize;
}
普通app安装在data/app目录下:
系统app安装在system/app目录,产生的应用数据保存在data/data/packagename下:
我用的是MATE9,没有data/data目录,通过context.getFilesDir()返回的是/data/user/0/com.cetcs.ecmapplication/files路径,在API19(4.4.4)上返回data/data/packagename:
还有一种外部存储路径:/sdcard/android/data/packagename:
没有root的手机上,外部存储路径的文件可以在手机上直接查看,内部存储路径下的文件,就是data/data/packagename是不能通过手机直接查看的,只有应用本身可以读写。
通过下面的代码得到内部和外部存储路径:
//根据android版本,返回/data/data/packagename/files,
//或者/data/user/0/com.cetcs.ecmapplication/files
File file1 = context.getFilesDir();
//返回/storage/emulated/0/Android/data/com.cetcs.ecmapplication/files
File file2 = context.getExternalFilesDir(null);
下面传上完整代码:
private static long getFileSize(File f) throws Exception
{
ECMLog.i_ecm(CLASS_TAG, "getFileSize called,f:" + f);
long size = 0;
if (f.isDirectory()){
File flist[] = f.listFiles();
if (flist == null || flist.length == 0){
ECMLog.i_ecm(CLASS_TAG, "folder:" + f + " has no files");
size = 0;
}else {
for (int i = 0; i < flist.length; i++)
{
if (flist[i].isDirectory())
{
size = size + getFileSize(flist[i]);
}
else
{
size = size + flist[i].length();
ECMLog.i_ecm(CLASS_TAG, "folder:" + f + " file:" + flist[i].getName() + " size:" + flist[i].length()/1024 + "KB");
if (i == flist.length -1){
ECMLog.i_ecm(CLASS_TAG, "folder:" + f + " total size:" + size/1024 + "KB");
}
}
}
}
}else {
size = f.length();
ECMLog.i_ecm(CLASS_TAG, "not directory,file:" + f + " size:" + size/1024 + "KB");
}
return size;
}
public static long printAppFileSizeInfo(Context context){
ECMLog.i_ecm(CLASS_TAG, "printAppFileSizeInfo called...");
//得到安装路径:/data/app/com.xxx.xxx/base.apk
String path=context.getPackageResourcePath();
ECMLog.i_ecm(CLASS_TAG, "PackageResourcePath:" + path);
File file = new File(path);
//得到/data/app/com.xxx.xxx
File resourceParentFolder = file.getParentFile();
ECMLog.i_ecm(CLASS_TAG, "resourceParentPath:" + resourceParentFolder);
long totalSize = 0;
long tmpSize = 0;
try {
tmpSize = getFileSize(resourceParentFolder);
totalSize += tmpSize;
ECMLog.i_ecm(CLASS_TAG, "PackageResource size:" + tmpSize);
} catch (Exception e) {
e.printStackTrace();
}
//返回:根据android版本,返回/data/data/packagename/files,或者/data/user/0/com.cetcs.ecmapplication/files
file = context.getFilesDir();
ECMLog.i_ecm(CLASS_TAG, "file:" + file);
if (file != null){
file = file.getParentFile();
try {
tmpSize = getFileSize(file);
ECMLog.i_ecm(CLASS_TAG, "data/data size:" + tmpSize);
totalSize += tmpSize;
} catch (Exception e) {
e.printStackTrace();
}
}
//返回:/storage/emulated/0/Android/data/com.cetcs.ecmapplication/files
file = context.getExternalFilesDir(null);
if (file != null){
file = file.getParentFile();
ECMLog.i_ecm(CLASS_TAG, "file:" + file);
try {
tmpSize = getFileSize(file);
ECMLog.i_ecm(CLASS_TAG, "External size:" + tmpSize);
totalSize += tmpSize;
} catch (Exception e) {
e.printStackTrace();
}
}
ECMLog.i_ecm(CLASS_TAG, "total size:" + totalSize);
return totalSize;
}
为了得到所有相关文件,把三个路径的根目录直接传进去计算文件大小了。
system/app目录下一般就直接是xxxxx.apk了,我们的app有一些库,所以创建了一个文件夹,把lib和apk放到里面:
梳理下这些路径:
1. system/app/xxx.apk:预装app的apk保存路径,通过adb push apk到root的手机;
2. data/app/packagename/xxx.apk:普通安装apk,保存apk的路径;
3. data/data/packagename:app内部数据,app私有;
4. /storage/emulated/0/Android/data/packagename:app外部数据,公有的。
获取外部存储路径根目录:
//返回:/storage/emulated/0
File fileFolder = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
ECMLog.i_ecm(CLASS_TAG, "fileFolder:" + fileFolder.getAbsolutePath());