您的位置:首页 > 其它

解决使用Debug.startMethodTracing后找不到对应的.trace文件

2018-03-23 17:16 459 查看
最近需要分析优化启动时间,查了资料准备使用在方法开始处加Debug.startMethodTracing()结束点加Debug.stopMethodTracing.搜了网上的博客,都是startMethodTracing()不传参数的话默认保存在/sdcard/dmtrace.trace(抄的时候都不去试试,唉) 。 由于懒,执行后直接去执行adb pull 。但是发现根本就没有生成这个文件。迷茫了。。没办法那就看下源码吧,最后还是找到了正解。



就像圈红所述,在第一存储(即内置)包名目录下建立文件。想到了应该是Android/data/目录,然后去找了一下,.trace文件果然在这。坑~。

而且还是用getExternalFilesDir()获取的路径。那就跟进去看下

/**
* Returns the absolute path to the directory on the primary shared/external
* storage device where the application can place persistent files it owns.
* These files are internal to the applications, and not typically visible
* to the user as media.
* <p>
* This is like {@link #getFilesDir()} in that these files will be deleted
* when the application is uninstalled, however there are some important
* differences:
* <ul>
* <li>Shared storage may not always be available, since removable media can
* be ejected by the user. Media state can be checked using
* {@link Environment#getExternalStorageState(File)}.
* <li>There is no security enforced with these files. For example, any
* application holding
* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to
* these files.
* </ul>
* <p>
* If a shared storage device is emulated (as determined by
* {@link Environment#isExternalStorageEmulated(File)}), it's contents are
* backed by a private user data partition, which means there is little
* benefit to storing data here instead of the private directories returned
* by {@link #getFilesDir()}, etc.
* <p>
* Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
* are required to read or write to the returned path; it's always
* accessible to the calling app. This only applies to paths generated for
* package name of the calling application. To access paths belonging to
* other packages,
* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} and/or
* {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required.
* <p>
* On devices with multiple users (as described by {@link UserManager}),
* each user has their own isolated shared storage. Applications only have
* access to the shared storage for the user they're running as.
* <p>
* The returned path may change over time if different shared storage media
* is inserted, so only relative paths should be persisted.
* <p>
* Here is an example of typical code to manipulate a file in an
* application's shared storage:
* </p>
* {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
* private_file}
* <p>
* If you supply a non-null <var>type</var> to this function, the returned
* file will be a path to a sub-directory of the given type. Though these
* files are not automatically scanned by the media scanner, you can
* explicitly add them to the media database with
* {@link android.media.MediaScannerConnection#scanFile(Context, String[], String[], android.media.MediaScannerConnection.OnScanCompletedListener)
* MediaScannerConnection.scanFile}. Note that this is not the same as
* {@link android.os.Environment#getExternalStoragePublicDirectory
* Environment.getExternalStoragePublicDirectory()}, which provides
* directories of media shared by all applications. The directories returned
* here are owned by the application, and their contents will be removed
* when the application is uninstalled. Unlike
* {@link android.os.Environment#getExternalStoragePublicDirectory
* Environment.getExternalStoragePublicDirectory()}, the directory returned
* here will be automatically created for you.
* <p>
* Here is an example of typical code to manipulate a picture in an
* application's shared stor
4000
age and add it to the media database:
* </p>
* {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
* private_picture}
*
* @param type The type of files directory to return. May be {@code null}
*            for the root of the files directory or one of the following
*            constants for a subdirectory:
*            {@link android.os.Environment#DIRECTORY_MUSIC},
*            {@link android.os.Environment#DIRECTORY_PODCASTS},
*            {@link android.os.Environment#DIRECTORY_RINGTONES},
*            {@link android.os.Environment#DIRECTORY_ALARMS},
*            {@link android.os.Environment#DIRECTORY_NOTIFICATIONS},
*            {@link android.os.Environment#DIRECTORY_PICTURES}, or
*            {@link android.os.Environment#DIRECTORY_MOVIES}.
* @return the absolute path to application-specific directory. May return
*         {@code null} if shared storage is not currently available.
* @see #getFilesDir
* @see #getExternalFilesDirs(String)
* @see Environment#getExternalStorageState(File)
* @see Environment#isExternalStorageEmulated(File)
* @see Environment#isExternalStorageRemovable(File)
*/
@Nullable
public abstract File getExternalFilesDir(@Nullable String type);


很长,但是意思是这个文件是根据包名建立的,4.4以后需要在manifest申请读写权限,人而且因为是在包名目录下,卸载后这些文件也将被一起干掉。

The type of files directory to return. May be {@code null}
*            for the root of the files directory or one of the following
*            constants for a subdirectory:


type是空的话返回根目录

源码重点



在ContextImpl具体实现,调用Environment.buildExternalStorageAppFilesDirs



注意这里方框圈里的getExternalFilesDir(type)[0] 拿到的数组第一个位置路径



看下mExternalDirsForApp是什么

public UserEnvironment(int userId) {
// See storage config details at http://source.android.com/tech/storage/ String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE);
String rawEmulatedSource = System.getenv(ENV_EMULATED_STORAGE_SOURCE);
String rawEmulatedTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET);

String rawMediaStorage = System.getenv(ENV_MEDIA_STORAGE);
if (TextUtils.isEmpty(rawMediaStorage)) {
rawMediaStorage = "/data/media";
}

ArrayList<File> externalForVold = Lists.newArrayList();
ArrayList<File> externalForApp = Lists.newArrayList();

if (!TextUtils.isEmpty(rawEmulatedTarget)) {
// Device has emulated storage; external storage paths should have
// userId burned into them.
final String rawUserId = Integer.toString(userId);
final File emulatedSourceBase = new File(rawEmulatedSource);
final File emulatedTargetBase = new File(rawEmulatedTarget);
final File mediaBase = new File(rawMediaStorage);

// /storage/emulated/0
externalForVold.add(buildPath(emulatedSourceBase, rawUserId));
externalForApp.add(buildPath(emulatedTargetBase, rawUserId));
// /data/media/0
mEmulatedDirForDirect = buildPath(mediaBase, rawUserId);

} else {
// Device has physical external storage; use plain paths.
if (TextUtils.isEmpty(rawExternalStorage)) {
Log.w(TAG, "EXTERNAL_STORAGE undefined; falling back to default");
rawExternalStorage = "/storage/sdcard0";
}

// /storage/sdcard0
externalForVold.add(new File(rawExternalStorage));
externalForApp.add(new File(rawExternalStorage));
// /data/media
mEmulatedDirForDirect = new File(rawMediaStorage);
}

// Splice in any secondary storage paths, but only for owner
final String rawSecondaryStorage = System.getenv(ENV_SECONDARY_STORAGE);
if (!TextUtils.isEmpty(rawSecondaryStorage) && userId == UserHandle.USER_OWNER) {
for (String secondaryPath : rawSecondaryStorage.split(":")) {
externalForVold.add(new File(secondaryPath));
externalForApp.add(new File(secondaryPath));
}
}

mExternalDirsForVold = externalForVold.toArray(new File[externalForVold.size()]);
mExternalDirsForApp = externalForApp.toArray(new File[externalForApp.size()]);
}


Environment初始化的时候拿到所有的路径,先添加内置的emulated,之后添加Secondary_Storage(物理外置卡) 到一个集合ArrayList.最后返回。所以说前面getExternalFilesDir(type)[0] 拿到的是内置SD卡的路径(即storage/emulated/0/…)



这是具体的常量值,刚好是Android/data/包名/files.之后调用buildpath返回路径即最终结果是:storage/emulated/0/Android/data/包名/files/dmtrace.trace

小结

有些事儿还是需要亲力亲为,看了源码就开朗了。可以参看这个文章介绍获取物理外置SD卡路径和读写 点我,求点赞~~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐