2017-05-08 28 views
0

我試圖在Android Studio中進行條件構建,在這裏我可以通過刪除任何多餘的庫依賴關係來減少生成的APK的大小,如果它們不需要特定分發。如何在Android中有條件地編譯JAR?

我有一些代碼,大致接近於以下內容:

public class MyClass { 

    /* Static Declarations. */ 
    public static final boolean USE_LIBRARY = false; 

    public void doSomething() { 
     // Are we using the library?  
     if(MyClass.USE_LIBRARY) { 
      // Do something with the library that we'd define in my build.gradle. 
      com.some.gradle.library.MyLibrary.doSomethingWithLibrary(); 
     } 
     else { 
      // Do something else. 
     } 
    } 

} 

如果我從我的搖籃依賴刪除com.some.gradle.library,我收到指示上面的代碼不能被編譯編譯錯誤。正如你所看到的,只要USE_LIBRARY保持不真實,我們絕不需要參考MyLibrary;甚至沒有實例化,因爲它沒有提到進口;這些只在運行時被侵犯。

我應該注意到,在實踐中,USE_LIBRARY是一個程序生成的常量,與應用程序的BuildConfig.java有關。

當然,編譯器可以確定這個代碼可以優化嗎?這是一種預處理器檢查,我可以解決嗎?

回答

1

找到了解決方案。我所採取的上述方法可能是,前提是您可以保證在運行時沒有庫代碼可以交互;這包括確保您的任何運行時類extend都不屬於任何父節點或implement接口,它們是庫的一部分。我能夠通過使用ClassyShark驗證代碼已被刪除。

的「絕招」是,當你要導出的庫聲明庫組件爲provided爲要構建變種假裝庫提供給您,並作爲compile的。

即使用兩生成異體libraryVariantemptyVariant,其經由編程開關buildConfigField 'boolean', 'USE_LIBRARY', 'X'USE_LIBRARY值。那麼你可以定義你的依賴關係如下:

dependencies { 
    // Actually package the library with the compiled APK. 
    libraryVariantCompile "com.some.gradle.library:-1" 
    // Ignore the library; just please the linting process. 
    emptyVariantProvided "com.some.gradle.library:-1" 
} 
2

我想在Android Studio中做一個條件構建,在那裏我可以通過刪除任何多餘的庫依賴關係來減小生成的APK的大小,如果他們不需要特定的分佈。

步驟#1:爲該「特定分配」定義產品風味。爲了這個答案的目的,我將這個foo。您還需要其他產品口味用於其他發行版。

步驟#2:更改您的compile語句,該語句將此JAR拉到fooCompile語句,因此它只會在foo版本上使用。

步驟#3:在每個產品口味的來源組(例如,src/foo/java/)中有MyClass的一個版本,其中foo中的那個引用該庫,而其他的則不是。

+0

這聽起來很有希望。我有階段1和階段2,但我不知道第三個甚至是一個選項!我會讓你知道我如何繼續,謝謝。 –

1

我想你可能會混淆Java運行時和編譯時過程的行爲。

在運行期間,您的代碼可以有條件地執行,並且庫調用可以被忽略,但是在編譯期間會處理所有代碼。

通過在編譯時引用庫,編譯時需要依賴關係。

但是,有一個名爲Proguard的實用工具,它是Android構建系統的一部分,它可以從apk中刪除未使用的字節碼。此外,請檢查@CommonsWare答案,如果您不是在不同版本中使用該庫,那麼構建類型允許您創建單獨的版本,而無需該庫

+0

感謝您的澄清。麻煩的是,即使是proguard似乎也無法消除這個庫! –