前言
相信很多工作幾年的Android程式設計師對Android的API都比較熟,呼叫起來也毫不含糊,實在不常用的類查一下API文件也能輕鬆搞定。
但是你們有沒有遇到過這樣的問題,客戶或者老闆提了一個需求,而Android自己的API是不支援這個功能的?我就遇到過這樣的問題,商顯裝置為了省電節約成本, 會在半夜沒人的時候自己關機,到了早上6點又自啟,然而Andorid系統從斷電到自啟是需要底層適配的,再或者就是要同步板子上的RTC時鐘(硬體時鐘,類似於電腦主機板上關機後依然記錄時間的一個模組)的時間
這一類問題,都是要先修改Android原始碼做到底層適配,然後匯入自編譯framework.jar包才能得以實現的,下面以同步RTC時鐘為例:
開始可以看到我們在frameworks下做了一些改動,透過新增jni呼叫底層的一些cpp中的方法,然後在AlarmManager.java類中新增定義,封裝自己的setRtcTime方法。
改動完畢之後,進行編譯燒錄,這樣我們機器的Android系統裡的AlarmManager類裡新增了一個叫做setRtcTime的方法,名字隨便你起,也就是相當於多了一個全新的API。那我們在這個機器的系統上跑的apk可以直接呼叫麼?我們試試。
新建一個專案,叫FrameWorkApp,封裝一個工具類NewAlarmHelper,可以呼叫我們的setRtcTime方法:
public class MainActivity extends AppCompatActivity { private Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Calendar calendar = Calendar.getInstance(); calendar.set(2020, 11, 12, 12, 12, 11); NewAlarmHelper.setRtcTime(MainActivity.this,calendar.getTimeInMillis()); } }); }}
好了,就是這樣,我們編譯生成apk,看一下結果如何。
Oh no,編譯都過不了,直接告訴你說沒有這個方法。這就是今天的主題所要說的東西了,你雖然在系統層已經做了適配,但是AndroidStudio它的API還是根據google預設的API來進行編譯,google怎麼會知道你自己要新增什麼方法。
那麼我們怎麼辦才能正常生成apk呢? 首先找到你的專案原始碼,我的這個專案原始碼是amlogic平臺,Android 9.0系統的,所以這篇部落格同樣適用於Android高版本這類問題的解決。
我們找到out\target\common\obj\JAVA_LIBRARIES\framework_intermediates目錄下的classes.jar檔案,這個檔案就是我們要的framework.jar包。
這個jar包才是可以供AS使用的,它有自己一定的大小,我這裡是21M左右,因平臺而異。而如果你天真的直接在out目錄下搜尋framework.jar也是可以搜到的。
但是這些jar包都是不起作用的,我剛開始在網上搜一些資料,大部分沒有點名這個問題,導致自己也走了很多的彎路,這些jar包都是幾kb左右,所以大家一定要找對檔案(一定是有大小的,而不是幾kb),不要走這樣的彎路。
既然我們找到了對應的jar包,那我們就把它重新命名為framework.jar,意思是這個jar包是framework相關的。
因為你這個專案可能不止一個人維護,或者說萬一你離職了,交接時沒有這麼細節的說明這個問題,那麼別的程式設計師看到這個名叫classes.jar的時候會一臉蒙圈。
說到導包,有人會說了,這個我知道,複製貼上到lib目錄下,然後Add As Library就可以了,下面的你就不用講了。
其實不然,這個和之前的jar包匯入有很大區別。那麼接下來,我就按部就班的教大家如何匯入這個我們自己編譯的framework.jar。
首先,我們把改好名字的framework.jar檔案複製貼上到lib目錄下,^_^(哈哈)。
然後,重點來了,不用右鍵選Add As Library,而是直接去開啟app目錄下的build.gradle檔案。
最後,在Project的build.gradle的allprojects中,將我們自己編譯的framework.jar包設定為優先於系統包,然後Sync Porject 。
// 設定framework.jar包優先系統包 gradle.projectsEvaluated { tasks.withType(JavaCompile) { options.compilerArgs.add('-Xbootclasspath/p:app/libs/framework.jar') } }
到這裡三步,我們已經成功把大象裝進了冰箱,在AS中匯入了自己編譯的framework.jar包,空口無憑,我們試試能不能編譯生成apk包吧。
系統時間已經修改,再看下硬體時鐘。
硬體時鐘2020-12-12 04:12,怎麼不是12:12呢 ???哈哈,因為硬體時鐘記錄的時間為格林威治標準時間,我們一般用的都是東八區北京時間,所以要比格林威治標準時間多加8個小時。
所以我們系統時間和硬體時鐘全部都設定成功!
最後最後,在這裡我也分享一份乾貨,由大佬收錄整理的 Android學習PDF+架構影片+原始碼筆記,還有高階架構技術進階腦圖、Android開發面試專題資料,高階進階架構資料幫助大家學習提升進階,也節省大家在網上搜索資料的時間來學習,也可以分享給身邊好友一起學習。