【Android 性能优化】应用启动优化 ( 方法追踪代码模板 | 示例项目 | SD 卡访问权限 | 示例代码 | 获取 Trace 文件 | Android Studio 查看文件)

简介: 【Android 性能优化】应用启动优化 ( 方法追踪代码模板 | 示例项目 | SD 卡访问权限 | 示例代码 | 获取 Trace 文件 | Android Studio 查看文件)

文章目录

一、 方法追踪代码模板

二、 追踪 Launch 页面的 onCreate 方法执行情况

1. 示例项目

2. SD 卡访问权限问题 ( 动态权限申请 )

3. MainActivity onCreate 方法追踪及动态权限申请

三、 查看 SD 卡根目录的 trace 文件

四、 Android Studio 中分析该 Trace 文件





一、 方法追踪代码模板


调用 Debug.startMethodTracing(traceFile.getAbsolutePath()) 开始追踪分析方法执行情况 , 传入文件路径作为参数 , 当执行 Debug.stopMethodTracing() 方法时 , 会将方法追踪信息保存到 traceFile.getAbsolutePath() 代表的文件路径中 ;


在下面的代码中 , 方法追踪信息被保存到了 SD 卡下的 Method_Trace 文件中 ;




1. 方法追踪使用流程 :



① 创建 File 对象 : 方法的执行信息 , 将被保存到该 File 文件中 ;


File traceFile = new File(Environment.getExternalStorageDirectory(), "Method_Trace");


② 开始方法追踪 : 在该方法中 , 需要传入上述 File 文件的绝对路径 , 才能向该 File 文件中保存方法执行信息 ;


Debug.startMethodTracing(traceFile.getAbsolutePath());


③ 停止方法追踪 : 调用该方法后 , 结束追踪 , 可以将 File 文件导出 , 并在 Android Studio 工具中分析方法执行情况 ;


Debug.stopMethodTracing();



2. 代码示例 :


// 1. 将追踪信息存放到该文件中
File traceFile = new File(Environment.getExternalStorageDirectory(), "Method_Trace");
// 2. 开启方法追踪
Debug.startMethodTracing(traceFile.getAbsolutePath());
// TODO 要追踪的内容
// 3. 停止方法追踪
Debug.stopMethodTracing();





二、 追踪 Launch 页面的 onCreate 方法执行情况




1. 示例项目


1 . 示例项目 : 以上一个项目直播推流的 MainActivity 为例 , 在该 Launch Activity 的 onCreate 方法中 , 添加上述方法追踪信息 , 追踪方法执行情况 , 项目地址 han1202012 / RTMP_Pusher ;




2. SD 卡访问权限问题 ( 动态权限申请 )


1. 权限问题 : 我用的是 Google Pixel 2 手机作为测试机 , 使用的是 Android 10 系统 , 此时出现动态权限问题 ;



2. SD 卡访问权限 : Debug.startMethodTracing(traceFile.getAbsolutePath()) 方法作用是将方法追踪信息写出到 SD 卡的文件中 , 因此这里必须 动态申请 SD 卡的访问权限 ;



3. 静态声明权限 : 在 AndroidManifest.xml 文件中添加 SD 卡的访问权限 : 最后两个是 SD 卡访问权限 ;


<!-- 前 4 个权限是读写权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<!-- 最后两个权限是 SD 卡访问权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


4. 动态权限申请 : MainActivity 中使用相关权限之前 , 必须先动态申请权限 , 否则无法进行方法追踪 ;



注意 : 动态权限申请 , 必须要在 Debug.startMethodTracing 方法之前调用 , 否则开始方法追踪在没有 SD 卡访问权限的情况下执行 , 直接崩溃 ;




3. MainActivity onCreate 方法追踪及动态权限申请


下面代码中有 ★ 的代码是方法追踪相关代码 ; 添加了 3 33 行方法追踪相关代码 ;


动态权限申请代码 : 其中 [   31 , 71   ] [ \, 31 , 71 \,][31,71] 行区间内的代码是动态权限申请相关代码 ;


方法追踪代码 : 第 88 , 90 , 124 88 , 90 , 12488,90,124 行代码是方法追踪相关代码 ;



package kim.hsl.rtmp;
import android.Manifest;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.Environment;
import android.view.SurfaceView;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import java.io.File;
public class MainActivity extends AppCompatActivity {
    /**
     * 显示图像的 SurfaceView 组件
     */
    private SurfaceView mSurfaceView;
    /**
     * 直播推流器
     */
    private LivePusher mLivePusher;
    /**
     * 需要获取的权限列表
     */
    private String[] permissions = new String[]{
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.INTERNET,
            Manifest.permission.MODIFY_AUDIO_SETTINGS,
            Manifest.permission.RECORD_AUDIO,
            Manifest.permission.CAMERA
    };
    /**
     * 动态申请权限的请求码
     */
    private static final int PERMISSION_REQUEST_CODE = 888;
    /**
     * 动态申请权限
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    private void initPermissions() {
        if (isLacksPermission()) {
            //动态申请权限 , 第二参数是请求吗
            requestPermissions(permissions, PERMISSION_REQUEST_CODE);
        }
    }
    /**
     * 判断是否有 permissions 中的权限
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    public boolean isLacksPermission() {
        for (String permission : permissions) {
            if(checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED){
                return true;
            }
        }
        return false;
    }
    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        /*
            此时应用首界面启动完成, 将主题恢复成其它主题
            此处也可以根据不同的设置, 为应用设置不同的主题
         */
        setTheme(R.style.AppTheme);
        super.onCreate(savedInstanceState);
        // 初始化权限
        initPermissions();
        // ★ 1. 将追踪信息存放到该文件中
        File traceFile = new File(Environment.getExternalStorageDirectory(), "Method_Trace");
        // ★ 2. 开启方法追踪
        Debug.startMethodTracing(traceFile.getAbsolutePath());
        setContentView(R.layout.activity_main);
        mSurfaceView = findViewById(R.id.surfaceView);
        // 创建直播推流器, 用于将采集的视频数据推流到服务器端
        // 800_000 代表 800K 的码率
        mLivePusher = new LivePusher(this,
                640, 480, 800_000, 10,
                Camera.CameraInfo.CAMERA_FACING_BACK);
        // 设置 Camera 采集的图像本地预览的组件, 在 mSurfaceView 界面先绘制摄像头
        // 此处要为 SurfaceHolder 设置 SurfaceHolder.Callback 回调 , 通过里面的回调函数
        // 驱动整个推流开始
        mLivePusher.setPreviewDisplay(mSurfaceView.getHolder());
        findViewById(R.id.button_play).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // rtmp://123.56.88.254/myapp/0
                // 0 相当于 直播的 密码
                // 配置好服务器后, 记录 IP 地址, 替换 123.56.88.254 IP 地址
                // rtmp://123.56.88.254/myapp/mystream 地址推流后
                // 可以直接在 RTMP 服务器端的主页, 使用 JWPlayer 观看直播内容
                // 网页地址是 http//123.56.88.254:8080/
                String rtmpServerAddress = "rtmp://123.56.88.254/myapp/mystream";
                mLivePusher.startLive(rtmpServerAddress);
                ((TextView)findViewById(R.id.textViewUrl))
                        .setText("推流地址 : " + rtmpServerAddress);
            }
        });
        // ★ 3. 停止方法追踪
        Debug.stopMethodTracing();
    }
}






三、 查看 SD 卡根目录的 trace 文件


应用启动完毕后 , onCreate 方法执行完毕 , 该方法追踪文件就会在 SD 卡根目录生成 ;


回顾下存放方法追踪信息的文件创建过程 , 将 Trace 信息存储到了 SD 卡根目录的 Method_Trace 文件中 ;


// ★ 1. 将追踪信息存放到该文件中
File traceFile = new File(Environment.getExternalStorageDirectory(), "Method_Trace");


image.png





四、 Android Studio 中分析该 Trace 文件


直接将该文件拖入 Android Studio 中即可 ;


image.png

目录
打赏
0
0
0
0
39
分享
相关文章
|
5月前
|
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
164 15
Android 系统缓存扫描与清理方法分析
Android远程连接和登录FTPS服务代码(commons.net库)
Android远程连接和登录FTPS服务代码(commons.net库)
71 1
探索安卓与iOS开发的差异:从代码到用户体验
【10月更文挑战第5天】在移动应用开发的广阔天地中,安卓和iOS两大平台各占半壁江山。它们在技术架构、开发环境及用户体验上有着根本的不同。本文通过比较这两种平台的开发过程,揭示背后的设计理念和技术选择如何影响最终产品。我们将深入探讨各自平台的代码示例,理解开发者面临的挑战,以及这些差异如何塑造用户的日常体验。
Android经典面试题之组件化原理、优缺点、实现方法?
本文介绍了组件化在Android开发中的应用,详细阐述了其原理、优缺点及实现方式,包括模块化、接口编程、依赖注入、路由机制等内容,并提供了具体代码示例。
104 2
🔥Android开发大神揭秘:从菜鸟到高手,你的代码为何总是慢人一步?💻
在Android开发中,每位开发者都渴望应用响应迅速、体验流畅。然而,代码执行缓慢却是常见问题。本文将跟随一位大神的脚步,剖析三大典型案例:主线程阻塞导致卡顿、内存泄漏引发性能下降及不合理布局引起的渲染问题,并提供优化方案。通过学习这些技巧,你将能够显著提升应用性能,从新手蜕变为高手。
72 2
Android调用Vue中的JavaScript代码
Android调用Vue中的JavaScript代码
117 3
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
本文介绍了如何将基于全志H713芯片的AOSP Android源码导入Android Studio以解决编译和编码问题,通过操作步骤的详细说明,展示了在Android Studio中利用代码提示和补全功能快速定位并修复编译错误的方法。
412 0
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
Android Studio导入Flutter项目提示Dart SDK is not configured
Android Studio导入Flutter项目提示Dart SDK is not configured
721 4
Android Studio利用Build.gradle导入Git commit ID、Git Branch、User等版本信息
本文介绍了在Android Studio项目中通过修改`build.gradle`脚本来自动获取并添加Git的commit ID、branch名称和用户信息到BuildConfig类中,从而实现在编译时将这些版本信息加入到APK中的方法。
195 0
Android Studio的使用导入第三方Jar包
Android Studio的使用导入第三方Jar包

热门文章

最新文章