【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

目录
相关文章
|
2月前
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
|
2月前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
60 15
Android 系统缓存扫描与清理方法分析
|
3月前
|
ARouter 测试技术 API
Android经典面试题之组件化原理、优缺点、实现方法?
本文介绍了组件化在Android开发中的应用,详细阐述了其原理、优缺点及实现方式,包括模块化、接口编程、依赖注入、路由机制等内容,并提供了具体代码示例。
48 2
|
2月前
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
128 0
|
Android开发 数据库
|
10天前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
15天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。