主頁 > 移動端開發 > Android Studio最全面編譯構建優化!!!

Android Studio最全面編譯構建優化!!!

2021-09-25 17:36:35 移動端開發

匯總:Android小白成長之路_知識體系匯總【持續更新中…】

目錄

  • 問題背景
  • Gradle構建流程
  • 優化前相關說明
  • 優化方案
    • 初始化速度優化
    • 配置速度優化
    • 執行速度優化
      • 對Gradle進行配置
        • 開啟并行編譯
        • 增大編譯記憶體
        • 開啟按需構建
        • 開啟構建快取
        • 開啟增量注解編譯
      • 對AS進行配置
        • 開啟離線模式
        • 更改AS記憶體大小
      • 更新最新Gradle版本
      • Module原始碼轉aar
      • 自定義執行的任務
    • Maven代理
    • 使用遠程共享構建快取
  • 總結

問題背景

公司專案使用Android Studio以及Gradle進行編譯,在每次修改代碼(哪怕是一行修改),再次編譯運行都要耗時三四分鐘,甚至更長時間,在初次編譯時更是長達十幾分鐘、極大的影響了開發效率,俗話說工欲善其事,必先利其器,這就對編譯速度進行一波優化,讓我們一步一步開始吧!

Gradle構建流程

首先了解一下Gradle的構建流程,整體分為三個階段:

  • 初始化階段:Gradle支持單專案和多專案構建,在初始化階段,Gradle從setting.gradle中讀取需要參與構建的模塊,并為每個模塊創建一個Project實體,
  • 配置階段:配置專案模塊和其所需要執行的腳本,也就是build.gradle等檔案
  • 執行階段:開始執行配置后的腳本任務

大體上了解了這些流程,我們就可以從這些流程上入手進行優化

優化前相關說明

當前作為驗證的電腦相關資訊:

  • 電腦名稱:MacBook Pro
  • 系統:Mac
  • 記憶體:8GB 1867MHz DDR3
  • 處理器:雙核Intel Core i5 2.7GHz
  • AS版本:4.1.1

驗證編譯速度的三個角度:

  • rebuild全工程,全部編譯
  • 新增一個方法,觸發java重新編譯
  • 修改一個xml,觸發資源重新編譯

比較資料獲取方式:rebuild嘗試三次取最低值,修改方法或xml嘗試五次取最低值

相關說明:

  • 由于電腦有時候卡頓或者別的原因影響編譯,會使得某次編譯耗時很長,因此不能取平均值作為參考
  • 編譯一般會一次比一次快,因為Android studio自帶快取
  • 開發階段本身就不會一直改配置,因此取最小值基本可以模擬日常使用情況
  • 因為主工程模塊比較龐大,因此驗證時使用的是主工程模塊的代碼,如果修改的是組件代碼,用時一般會更少
  • 每一次資料統計使用的方案繼承了它前面所有的優化方案
  • 修改方法和xml用apply changes

優化方案

從整體構建流程可以得知,我們整體上需要從三個方面進行優化:

  • 初始化速度優化
  • 配置速度優化
  • 執行速度優化

其中執行的程序占比是最大的,所以重心放在執行速度優化上

初始化速度優化

一般初始化程序任務較少本身就已經很快了,但仍然可以做一些處理,以達到最佳狀態:

  • 當組件化程度較高時,在開發某個特定功能程序中有些組件是不需要引入的,此時可以在setting.gradle中移除不需要引入的組件模塊,可以減少初始化時間
  • setting.gradle中include之前盡量不寫過多代碼

配置速度優化

配置階段主要是對各個build.gradle進行決議,因此可以注意以下幾點:

  • 按需引入模塊,減少build.gradle的決議
  • build.gradle中盡量少做耗時操作,例如讀取系統時間動態配置apk的名稱組成
  • 在開發階段不是必要執行的任務,可以寫判斷避免這些任務的配置,例如一些位元組碼插樁,性能監控之類的

執行速度優化

此階段存在的大量的任務需要執行,因此優化的點也非常的多

對Gradle進行配置

開啟并行編譯

開啟后會并行執行多個任務,大幅度減少編譯時間,只需要在gradle.properties中添加:

org.gradle.parallel=true

增大編譯記憶體

由于大家的電腦配置都不一樣,因此具體設定多大記憶體需要根據個人情況進行合理配置,一般在gradle.properties里已經有相關配置,可以對該配置進行修改,例如

org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

同時在主工程模塊的build.gradle中進行修改:

dexOptions {
	javaMaxHeapSize "4g"
	}

值得注意的是,javaMaxHeapSize的值需要比org.gradle.jvmargs設定的值少512m以上,而且org.gradle.jvmargs的值并不是設定越高越好,根據驗證,最好配置為系統記憶體的1/3,最多不要超過1/2,在部分檔案中顯示,高版本中javaMaxHeapSize中不再需要配置javaMaxHeapSize,只需要配置org.gradle.jvmargs即可,查閱了許多資料都沒說清楚,所以暫時都配置好了

開啟按需構建

對沒有更改的模塊不再進行編譯,非常適合已經組件化的專案,在gradle.properties中添加:

org.gradle.configureondemand=true

開啟構建快取

直接使用之前生成的快取,不再進行構建,在構建時任務后面會顯示FROM CACHE,在gradle.properties中添加:

org.gradle.caching=true

開啟增量注解編譯

支持注解增量編譯,不會重新觸發編譯(gradle高版本中需要移除),在gradle.properties中添加:

android.enableSeparateAnnotationProcessing=true

資料對比(并行編譯是優化前已經開啟,因此以下時間不包括并行編譯的優化):

rebuild修改方法修改xml
配置優化前4m46s46s22s
配置優化后2m39s42s20s
收益減少44%減少8%減少9%

對AS進行配置

開啟離線模式

開啟離線模式后不會再開始的時候去檢測依賴是否有更新,也不會去下載相關更新的依賴,首次構建不能開啟,否則無法完成構建,后續構建可以開啟,在某些情況下將大幅度改善編譯速度,強烈推薦開發階段使用,點擊下圖中的圖示的按鈕即可開啟離線模式,有些版本顯示為類似wifi的圖示,再次點擊取消離線模式:

在這里插入圖片描述

更改AS記憶體大小

點擊AS的Help選單項,選中Change Memory Settings選項,如圖:

在這里插入圖片描述

彈出如下圖彈框,把Maxinum Heap Size 修改為合適值,具體修改值根據自身電腦記憶體配置選擇

在這里插入圖片描述

資料對比:

rebuild修改方法修改xml
AS配置修改前2m39s42s20s
AS配置修改后2m16s37s16s
收益減少14%減少11%減少20%

更新最新Gradle版本

由于gradle在新版本中一般都會對構建速度進行進一步的優化,因此保持最新的gradle版本可以獲得最佳的構建體驗,更新方式如下:

  • 首先在gradle-wrapper.properties中進行gradle版本的配置:

    distributionUrl=https\:``//services.gradle.org/distributions/gradle-6.7.1-all.zip
    
  • 然后在根目錄下的build.gradle中更新gradle插件版本:

    classpath 'com.android.tools.build:gradle:4.1.1'
    

更新到6.x以上可能出現的問題和解決方案:

  1. 報例外:

    FAILURE: Build failed with an exception.
    * What went wrong:
    A problem occurred configuring project ':live'.
    > Failed to notify project evaluation listener.
       > org.gradle.api.tasks.TaskInputs.property(Ljava/lang/String;Ljava/lang/Object;)Lorg/gradle/api/tasks/TaskInputs;
       > Could not get unknown property 'additionalParameters' for task ':live:dexBuilderDebug' of type com.android.build.gradle.internal.tasks.DexArchiveBuilderTask.
    * Try:
    Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    * Exception is:
    org.gradle.api.ProjectConfigurationException: A problem occurred configuring project ':live'.
        at org.gradle.configuration.project.LifecycleProjectEvaluator.wrapException(LifecycleProjectEvaluator.java:75)
        ......
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    Cause 2: groovy.lang.MissingPropertyException: Could not get unknown property 'additionalParameters' for task ':live:dexBuilderDebug' of type com.android.build.gradle.internal.tasks.DexArchiveBuilderTask.
        at org.gradle.internal.metaobject.AbstractDynamicObject.getMissingProperty(AbstractDynamicObject.java:85)
        ......
        at java.lang.Thread.run(Thread.java:748)
     
    * Get more help at https://help.gradle.org
    

    這是當前greenDao版本過低導致的,更新greenDao版本即可,在根目錄的build.gradle下修改版本:

    classpath 'org.greenrobot:greendao-gradle-plugin:3.3.0'
    
  2. 報例外:

    FAILURE: Build failed with an exception.
    * Where:
    Build file '/Users/uxin/AndroidStudioProjects/Pika/UXLiveOverseas/live/build.gradle' line: 253
    * What went wrong:
    A problem occurred configuring project ':live'.
    > Could not get unknown property 'additionalParameters' for task ':live:dexBuilderDebug' of type com.android.build.gradle.internal.tasks.DexArchiveBuilderTask.
    * Try:
    Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    * Exception is:
    org.gradle.api.ProjectConfigurationException: A problem occurred configuring project ':live'.
        at org.gradle.configuration.project.LifecycleProjectEvaluator.wrapException(LifecycleProjectEvaluator.java:75)
        ......
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    Caused by: groovy.lang.MissingPropertyException: Could not get unknown property 'additionalParameters' for task ':live:dexBuilderDebug' of type com.android.build.gradle.internal.tasks.DexArchiveBuilderTask.
        at org.gradle.internal.metaobject.AbstractDynamicObject.getMissingProperty(AbstractDynamicObject.java:85)
        ......
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
     
    * Get more help at https://help.gradle.org
    

    sdk 21之前,一般會使用第三方multidex的依賴開啟dex的分塊,而sdk 21之後,官方自帶multidex,因此需要去掉第三方的multidex

    • 在主工程模塊的build.gradle中,洗掉掉multidex的依賴和自定義任務:

      //implementation 'androidx.multidex:multidex:2.0.0'
      
      //    afterEvaluate {
      //        tasks.matching {
      //            it.name.startsWith('dex')
      //        }.each { dx ->
      //            if (dx.additionalParameters == null) {
      //                dx.additionalParameters = ['--multi-dex']
      //            } else {
      //                dx.additionalParameters += '--multi-dex'
      //            }
      //        }
      //    }
      
    • 在自定義的Application類中洗掉multidex的初始化:

      //import androidx.multidex.MultiDex;
      
      //MultiDex.install(this);
      
  3. 報例外:

    FAILURE: Build failed with an exception.
    * Where:
    Build file '/Users/xxx/Projects/xxx/xxx/xxx/build.gradle' line: 1
    * What went wrong:
    A problem occurred evaluating project ':live'.
    > Failed to apply plugin 'com.android.internal.application'.
       > The option 'android.enableSeparateAnnotationProcessing' is deprecated.
         The current default is 'false'.
         It was removed in version 4.0 of the Android Gradle plugin.
         This feature was removed in AGP 4.0
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    * Get more help at https://help.gradle.org
    

    這是上面新添加的注解增量編譯欄位已經在gradle新版本中被移除了,所以應該去掉,在gradle.properties中洗掉:

    #android.enableSeparateAnnotationProcessing=true
    
  4. 報例外:

    private static final String LIBRARY_VERSION = ". Version: " + BuildConfig.VERSION_NAME;
                                                                               ^
    符號: 變數 VERSION_NAME
    位置:BuildConfig
    

    由于versionNameversionCode沒有多大差別,為了防止概念混淆,官方去掉了VERSION_NAME,因此我們專案中如果仍然需要用到,可與自定義buildConfigVERSION_NAME,在報錯的模塊的build.gradle中配置:

    defaultConfig {
        minSdkVersion MIN_SDK_VERSION as int
        targetSdkVersion TARGET_SDK_VERSION as int
        versionCode 2
        versionName "1.0.1"
        buildConfigField 'String', 'VERSION_NAME', "\"" + versionName + "\""
    }
    
  5. 報例外:

    
    /Users/xxx/Projects/xxx/xxx/xxx/xxx/src/main/java/com/xxx/base/utils/Utils.java:86: 錯誤: 找不到符號
          intent.putExtra(PAKAGENAME, BuildConfig.APPLICATION_ID);
                                                               ^
      符號: 變數 APPLICATION_ID
      位置:BuildConfig
    

    Gradle高版本中為了防止library里使用BuildConfig.APPLICATION_ID導致id和appication本身的id理解混淆,需要改為新的欄位:

    BuildConfig.LIBRARY_PACKAGE_NAME
    
  6. 報例外:

    
    /Users/xxx/Projects/xxx/xxx/xxx/xxx/src/main/java/com/xxx/base/view/ShareScreenShotDialog.java:205: 錯誤: 找不到符號
                                            shareInfo.setWeiboCopyWriter(String.format(mContext.getString(R.string.novel_share_intro_wb_empty),
                                                                                                                  ^
      符號: 變數 novel_share_intro_wb_empty
      位置: 類 string
    

    Gradle高版本不允許語言配置中默認語言配置為空,所以需要在default string中添加上報錯的那部分string

  7. 報例外:

    Execution failed for task ':live:transformClassesWithAjxForRelease'.
    > Cannot cast object 'com.android.build.gradle.internal.pipeline.TransformTask$2$1@6fe77eee' with class 'com.android.build.gradle.internal.pipeline.TransformTask$2$1' to class 'com.android.build.gradle.internal.pipeline.TransformTask'
    

    這是由于aspectjx版本過低導致,更新版本即可,在根目錄的build.gradle中修改:

    classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.10'
    

資料對比:

rebuild修改方法修改xml
Gradle更新前2m16s37s16s
Gradle更新后1m15s33s12s
收益減少44%減少10%減少25%

Module原始碼轉aar

隨著業務量的增大,module的引入也會增多,每個module在編譯的時候都需要花費一定的時間,即使新版本gradle對未修改并具有快取的module不進行編譯,但取快取也需要一定時間,把module轉化成aar后就不再需要每次都進行編譯或者取快取,可以減少一部分時間

Module轉aar優化步驟如下:

  1. 對每個module進行Build->Make module xxx生成aar在build/output/aar

  2. 新建一個module,隨意取名字,把其他module生成的aar復制到新建module的libs下,同時把其他module的libs下的aar包也同樣復制到新建module的libs下(因為aar包不會包含自己依賴的其他aar包),也可以不新建module,直接放到主工程的libs下

  3. 把新建module的src下其他檔案和檔案夾洗掉,只留下main檔案夾和AndroidManifest.xml檔案

  4. AndroidManifest.xm里的application洗掉

  5. 在新建module的build.gradle中把其他module所參考的aar依賴全部復制過來,同時依賴上其他幾個module制作的aar

  6. 在根目錄的build.gradle中修改:

    flatDir {
            dirs 'libs',project(':aar的module').file('libs')
    }
    

用一個新的module來存放aar的好處:

  • 和主工程模塊隔開,不需要把aar都復制到主工程的libs,也不需要把依賴寫在主工程模塊的依賴中
  • 可以在setting.gradle中直接判斷選擇aar編譯還是原始碼編譯
  • 某個組件更新了可以編譯一下直接替換aar檔案,即時更新

擴展:

可以做一個全域變數控制使用組件原始碼或者aar,操作步驟如下:

  1. setting.gradle中新增全域開關

    #是否修改組件代碼
    isModifyInComponent=false
    
  2. 在主工程模塊的build.gradle中修改:

    def modifyInComponent = isModifyInComponent.toBoolean()
    flatDir {
        if (modifyInComponent) {
            dirs 'libs',
                    project(':原始碼的module').file('libs'),
        }else {
            dirs 'libs',project(':aar的module').file('libs')
        }
    }
     
    if (modifyInComponent) {
        implementation project('原始碼的module')
    } else {
        implementation project('aar的module')
    }
    
  3. setting.gradle中修改:

    include ':app
    if (isModifyInComponent.toBoolean()) {
        include ':原始碼的module'
    } else {
        include ':aar的module'
    }
    

最好的方式是搭建私服maven倉庫用來存放aar,直接依賴就完成了,更加方便而且容易管理,這里后續再寫相應的文章

資料對比:

rebuild修改方法修改xml
組件原始碼1m15s33s12s
組件aar50s28s11s
收益減少33%減少15%減少8%

自定義執行的任務

在構建程序中,有部分task是為了優化app而執行的,這些task在開發程序中并不需要執行,只需要在正式打包的時候執行即可,因此可以暫時關閉這些任務,以減少執行時間,可以引入一個全域變數當做開關,然后在這些任務插件引入的地方做判斷,按需執行,

操作步驟如下:

  1. gradle.properties中定義一個開關

    #開啟快速編譯模式,快速編譯舍棄了一些配置,可以較快編譯執行app,適合開發除錯階段
    isFastBuildMode=false
    
  2. 在主工程模塊的build.gradle中做判斷,例如下面的:

    def fastBuildMode = isFastBuildMode.toBoolean()
    if (fastBuildMode) {
        repositories {
            flatDir {
                    dirs 'libs',
                            project(':aar的module').file('libs')
            }
        }
    } else {
        apply plugin: 'org.greenrobot.greendao'
        apply plugin: 'walle'
        apply plugin: 'com.didiglobal.booster'
        apply plugin: 'android-aspectjx'
        repositories {
            flatDir {
                    dirs 'libs',
                            project(':原始碼的module').file('libs')
            }
        }
        greendao {
            schemaVersion 2
            targetGenDir 'src/main/java'
        }
        walle {
           ...
        }
     
        aspectjx {
            exclude 'com.alipay', 'com.tencent', 'com.squareup.leakcanary'
        }
    }
     
    if (fastBuildMode) {
        ndk {
            abiFilters 'armeabi-v7a'
        }
        resConfigs "cn", "xhdpi"
     
    } else {
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a'
        }
    }
    

注意:開啟快速編譯開關會關閉一些任務,所以可能會導致一些不可預知的問題,如果除錯程序中出現例外,可以關閉快速編譯開關重新嘗試,在打包apk發布的時候一定要記得關閉快速編譯開關

資料對比:

rebuild修改方法修改xml
關閉快速編譯50s28s11s
開啟快速編譯38s13s11s
收益減少24%減少53%持平

Maven代理

前面說過可以創建私服maven用來存放生成的aar,其實也可以用私服maven來代理需要下載的依賴,放在內部網路倉庫中,需要的時候直接從內網中讀取,而無需去遠程maven倉庫讀取,這對一些使用外網的maven倉庫的專案具有非常大的幫助,如果不想自己搭建,也可以使用阿里云的鏡像maven倉庫,里面有常用的一些倉庫鏡像,搭建方法后續更新一篇文章來說明

使用遠程共享構建快取

前面提到過開啟快取的方式,但是那只針對于本地快取,在首次編譯時,快取為空,仍需要大量的時間進行編譯,但是在公司開發程序中,通常已經有同事的機器或者CI構建已經進行了編譯構建,我們能不能用某種方式來使用他們的快取呢?這樣就解決了首次編譯時間過長的困境,辦法總比困難多,對共享構建快取感興趣的可以去查看這篇文章:Gradle使用遠程構建快取

總結

比較安全簡單優化方案:

  • 開啟并行編譯、按需構建、構建快取
  • 開啟注解增量編譯(Gradle插件4.0以下)
  • 開啟離線模式
  • 使用apply changes
  • 修改JVM大小

需要適配的優化方案:

  • 升級gradle及其插件
  • 使用官方muitidex

只適合除錯開發階段的極速方案:

  • module轉aar
  • 按需自定義執行任務

更深入的優化:

  • 自定義撰寫優化插件,提高快取命中率等

  • 私服maven鏡像代理

  • CI共享構建快取

Mac系統總收益:

rebuild修改方法修改xml
優化前4m46s46s22s
優化后38s13s11s
收益減少86%減少46%減少50%

Windows 系統驗證

配置:

  • 處理器:i7-10510U 2.3GHz
  • 記憶體:8GB
  • 固態硬碟

總收益:

rebuild修改方法修改xml
優化前10m30s2m33s12s
優化后1m9s12s9s
收益減少89%減少92%減少25%

資料可能不完全準確,但編譯速度是肉眼可見地飛升,優化后可以大幅度減少編譯時間,這時間拿去喝咖啡它不香嘛,如果經費充足,再更新一波電腦配置,速度直接起飛,少加班就靠這個優化了!

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/302815.html

標籤:其他

上一篇:受眾同步管理功能上線,讓你的活動禮包發對人

下一篇:Android開發一個簡單的互動式App

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more