1. 程式人生 > >DIY Android之一--原生Android系統主題支援的設計和實現(來自本人cnblogs部落格)

DIY Android之一--原生Android系統主題支援的設計和實現(來自本人cnblogs部落格)

口號:Android只是個Demo。

智慧手機何其多,Symbian、WP、Android...,問題是原生的Android系統不支援主題定製。

於是我等看著花哨的主題資源包在市場上氾濫,前提:你先下載一個執行這些主題資源的應用程式APK包先。

但是...... 原生Android系統是不願意還是不能夠支援主題呢?以後會不會支援呢?

不管了,既然看Android原生主題支援功能不夠,本文就來嘗試一下如何通過修改Android原生程式碼來實現主題支援。

============================= 環境與步驟=================================

軟體版本:Android JellyBean

步驟:

I.原生Android主題支援需要涉及的部分

II.涉及部分在原生系統中的邏輯及修改

III.對周邊模組的影響和支援

=============================原生Android主題支援需要涉及的部分=================================

既然是要支援主題,也就是說系統需要支援和管理多套主題資源包,並且應用可以用相同的資源ID來訪問不同資源包中對應的資源。

因此我們首先分析一下Android系統的資源訪問流程。

對應用來說,資源訪問主要有下面三種方式:

第一、比較普遍的方式是使用xml定義,並且通過AAPT工具生成一個R檔案,列出資源的索引來讓Android系統自己去遍歷整個資源樹的方式來訪問。

第二、通過Resources介面來訪問,使用Resources類的getDrawable、getString等介面來獲取資源。

第三、通過AssetManager類的介面去訪問,使用這個類的open方法來返回一個InputStream物件得到資源。

其實這三個訪問方式只是Android資源訪問中整個流程中在不同層次對外提供的三個介面,到底層的實現都是殊途同歸的。

第一種的xml定義的資源解析的邏輯在Resources.java檔案的loadXmlResourceParser函式中,實際上也是呼叫的第三類介面,如下圖:

因此我們實際上需要修改的部分主幹是在訪問資源具體路徑前,按照當前系統主題設定訪問不同資源APK下的檔案

即是把原生Android中資源ID和資原始檔路徑之間一對一的關係改為一對多的關係。

例子如下:如果原有資源ID和資原始檔路徑關係為:

R.drawable.image01 = 0x7F020001

通過系統的資源查詢之後找到檔案路徑為 /system/app/frameworks-res.apk下的res/drawable_hdpi/icon.png

在AssetManager native中去讀取資源並上傳。

那麼我們需要做的是在傳入路徑去讀取資源時把檔案路徑替換為/data/app/SystemTheme01.apk下的res/drawable_hdpi/icon.png

=============================涉及部分在原生系統中的邏輯及修改=================================

為了完成上篇所提到的修改,我們依上圖分析一下原生系統中從傳入資源ID到生成需要訪問的資原始檔的路徑的過程:

Java層:

Resources類:

Android在Java層為應用層訪問不同型別的資源提供了一系列介面,這些介面被封裝在Resources類中,例如訪問字串資源的介面getString(),訪問Drawable型別資源的介面getDrawable()等等。該類還管理著另外兩個重要的類:Configuration和AssetManager。

Configuration類:

Configuration類中主要儲存了當前的系統配置資訊,例如字型、語言等,在應用呼叫Resources類的介面去獲取資源的時候,Resources類會通過Configuration類來讀取當前的系統配置資訊,再結合介面中收到的應用請求獲取的資源ID來獲取對應的資源。

AssetManager類:

AssetManager類提供了以資料流的方式訪問應用程式資源的方法。它主要是通過Native層的方法來實現訪問資源的。AssetManager管理的資源主要有兩個來源:一是應用程式的資源,通過訪問應用程式的APK檔案來得到;另外一個是系統資源,是通過訪問包含系統資源的APK檔案來獲得。

Native層:

AssetManager Native類:

AssetManager Native類提供了對資原始檔路徑以及資原始檔的操作支援,提供了諸如掃描APK的res路徑下的資料夾和檔案、對APK進行解壓縮、維護ResTable類以及部分Cache加速檔案的功能。

Asset類:

Asset類是所有型別資源類的基類,它提供了絕大部分對資源的操作實現和定義,是Android資源訪問和檔案訪問層之間的橋樑,也是需要修改主幹部分的核心。它封裝了整個Android資源訪問中對資原始檔的路徑查詢以及資源從檔案到資料流的轉換過程。在應用傳入資源ID來請求資源的時候,AssetManager會使用該類的create函式去生成一個新的資源物件,並使用讀出的資源資料流賦給該物件,最後返回給上層應用。

下圖列出了系統原有邏輯及需要修改的部分:

上面的部分已經分析了資源訪問過程中需要修改的部分,但是除了訪問流程的主幹之外,

系統在以下幾個部分對資源訪問效率做的優化同樣會受到我們修改資源ID對應關係的影響。

系統的預載入資源流程

原有邏輯:

系統在啟動的過程中會把系統常用的資源進行預載入,  

此邏輯位於frameworks/base/core/java/com/android/internal/os/ZygoteInit.java -- preloadResources函式

在此函式中會呼叫Resources.java中函式來對com.android.internal.R.array.preloaded_XXX的資源陣列中對應的資源進行預載入,

這個流程中會通過for迴圈預載入三類資源Drawable、ColorStateList、ColorDrawable,

並且存在對應的sPreloadedDrawables、sPreloadedColorStateLists、sPreloadedColorDrawables三個LongSparseArray的陣列中。

修改邏輯:

因為主幹部分已經對系統資源即framework-res.apk的資源進行了分別的處理,所以開機預載入的部分可以不做處理,

但是在主題變化之後,預載入的資源還是系統啟動時候的資料,所以需要對三個陣列進行清除或者啟動後臺服務重新進行預載入流程。

修改檔案:Resources.java

實現功能:在系統使用的主題包變化之後清除預載入資源陣列即上面提到的三個LongSparseArray陣列(可以考慮後臺重新載入新主題資源資料到陣列中)。

系統訪問中的資源快取機制(清除cache)

原有邏輯:

在系統每次訪問資源的過程中,查詢資源的順序是 預載入資源->Cache資源->資原始檔

並且在每次通過資原始檔的方式查詢到資源之後會把此資源加入到Cache中,加速下次訪問速度。

修改邏輯:

在主題設定被使用者修改之後,原有快取中的資料是上個主題包的檔案內容,需要清除。

============================= 對周邊模組的影響和支援=======================================

另:需要提供使用者可以管理主題包的應用程式

原有邏輯:(無)

修改邏輯:

使用者在安裝了主題包之後,需要提供一個應用來維護當前系統上已經存在的資源主題包。

應用需要實現功能:掃描、預覽、應用、解除安裝當前手機上已經安裝的主題資源包。

主要涉及:PackageManager介面、systemProperty讀寫。

主題改變之後通知應用的廣播

原有邏輯:

系統原有通知機制是ACTION_CONFIGURATION_CHANGE的Intent來通知應用系統配置改變,

如果應用不處理,系統會預設為應用更新系統配置(Activity資源、佈局等的重新載入)。

修改邏輯:

在系統判斷是否需要傳送CONFIGURATION_CHANGE的邏輯中加入如下邏輯:

如果當前系統主題資源包發生變化,需要傳送CONFIGURATION_CHANGE。

草草完成Demo設計和實現,僅僅算是把功能實現了,歡迎大家繼續優化、討論。

相關推薦

DIY Android之一--原生Android系統主題支援設計實現來自本人cnblogs部落

口號:Android只是個Demo。 智慧手機何其多,Symbian、WP、Android...,問題是原生的Android系統不支援主題定製。 於是我等看著花哨的主題資源包在市場上氾濫,前提:你先下載一個執行這些主題資源的應用程式APK包先。 但是...... 原生Android系統是不願意還是不能夠支援

自動升級系統OAUS的設計實現 附最新原始碼

private void button1_Click(object sender, EventArgs e) { int changedCount = 0; int addedCount = 0; List<FileUnit&g

資料訪問層的設計實現分散式系統

(1)如何對外提供資料訪問層的功能 資料訪問層就是方便應用進行資料讀寫訪問的抽象層,在該層上解決各個應用通用的訪問資料庫的問題。 上圖顯示了三種方式,第一種是為使用者提供專有API,不過不推薦,通用

Delphi - 手把手教你基於D7+Access常用管理系統架構的設計實現 更新中

前言   從事軟體開發工作好多年了,學的越深入越覺得自己無知,所以還是要對知識保持敬畏之心,活到老,學到老! 健身和程式碼一樣都不能少,身體是革命的本錢,特別是我們這種高危工種,所以小夥伴們運動起來!有沒有健身擼鐵,體脂現在是多少呀?明年(2019/03/22)徐州的馬拉松有沒有報名呀!?   扯的有點遠了,

android使用webview上傳檔案(支援相簿拍照),支援最高6.0安卓系統改進版

首先學習 http://blog.csdn.net/woshinia/article/details/19030437 對input file的支援1.注意 mUploadMessage.onReceiveValue(Uri.parse("")); 必須得到呼叫,無論使用者是否選了圖,否則會出現再點選不響應

Bodymovin:BodymovinLottie:把AE動畫轉換成HTML5/Android/iOS原生動畫 大殺器BodymovinLottie:把AE動畫轉換成HTML5/Android/iOS原生動畫

轉自:https://www.cnblogs.com/zamhown/p/6688369.html 大殺器Bodymovin和Lottie:把AE動畫轉換成HTML5/Android/iOS原生動畫   前段時間聽部門老大說,Airbnb出了個移動端的動畫庫Lottie,可

android使用webview上傳檔案(支援相簿拍照)

最近需要做一個專案,需要呼叫伺服器段的一些網頁來選擇檔案,剛開始還挺糾結的,不知從何下手,網上大致預覽了大神們走過的路,他們傳統的方式都是使用一下程式碼: publicvoid openFileChooser(ValueCallback<Uri> uploa

Android Studio 2.3.3 添加ksoap2的引用拒絕網上其他的忽悠,也適用於添加其他Jar的引用

ima mage androi img 適用於 網上 .com 2.3 ksoap2 Android Studio 2.3.3 添加ksoap2的引用(拒絕網上其他的忽悠),也適用於添加其他Jar的引用

Android中關於項目中對Thread的管理不是線程池

lan ole 問題 直接 per dma 之前 ron move 背景 項目中對於一些並不復雜的耗時操作,比如計算,不頻繁操作數據庫等,因為沒必要使用線程池,所以之前項目會直接使用new Thread的方式,時間一長,回頭再看,原來new Thread之處已經很多

Android 雙擊退出程序實現有側滑界面

是的 tro raw idt style tap sys .com ges 大家好,今天帶來雙擊退出程序實現方法,我知道,網上也是有許多關於雙擊退出程序實現的方法,所以,聽見當然是給大家帶來不一樣的雙擊退出的實現方法。 首先帶來的便是關於onKeyDown和onKe

Android音視頻通話過程中最小化成懸浮框的實現類似Android8.0畫中畫效果

apk 添加 touch null cas 如果 動態添加 int sta 關於音視頻通話過程中最小化成懸浮框這個功能的實現,網絡上類似的文章很多,但是好像還沒看到解釋的較為清晰的,這裏因為項目需要實現了這樣的一個功能,今天我把它記錄下來,一方面為了以後用到便於自己查閱,一

基於Android簡單備忘錄的設計實現附git原始碼連結

前言 課程作業需要,於是忙活兩天寫了一個簡單的備忘錄,使用了ListView,SQLite。 開發環境:Android Studio 原始碼連結:https://gitee.com/zg0212/Memoire 功能截圖 主頁面 新建頁面

Android:答題APP的設計實現mysql+jsp+Android Android:答題APP的設計實現mysql+jsp+Android

Android:答題APP的設計與實現(mysql+jsp+Android) 還沒有整理完,待續…… 學校開了Android課,最後讓交一個大作業。正好拿來練練手,記錄下思路。也希望能給有需要的朋友們一些幫助。恩,純小白教程,大神們可以繞路了。 作業的題目是這樣的: 考試A

Android】中微信搶紅包助手的實現程式碼整理

實現原理   通過利用AccessibilityService輔助服務,監測螢幕內容,如監聽狀態列的資訊,螢幕跳轉等,以此來實現自動拆紅包的功能。關於AccessibilityService輔助服務,可以自行百度瞭解更多。 程式碼基礎: 1.首先宣告一個RedPac

Android中對話方塊右上角關閉懸浮按鈕的實現總結

其實很簡單,步驟如下: 1、需要把對話方塊的預設背景改為透明。 方法:自定義Dialog的樣式。 <!--對話方塊透明背景--> <style name="Translucent_NoTitle" parent="android:style/Theme

Android:答題APP的設計實現mysql+jsp+Android

還沒有整理完,待續…… 學校開了Android課,最後讓交一個大作業。正好拿來練練手,記錄下思路。也希望能給有需要的朋友們一些幫助。恩,純小白教程,大神們可以繞路了。 作業的題目是這樣的: 考試APP系統: 1)要求有使用者登陸功能:從遠端伺服器進行登

Android---多執行緒:繼承Thread 類實現Runnable 介面的區別

參考: Java中執行緒的建立有兩種方式: 1、通過繼承Thread類,重寫Thread的run()方法,將執行緒執行的邏輯放在其中。多個執行緒分別完成自己的任務。 2、通過實現Runnable介面,例項化Thread類。多個執行緒共同完成一個任務

基於Android手機平臺的“晨起”app設計實現

**基於Android手機平臺的“晨起”app設計與實現** 基於Android手機平臺的“晨起”app設計與實現mysql資料庫建立語句 基於Android手機平臺的“晨起”app設計與實現oracle資料庫建立語句 基於Android手機平臺的“晨起”app設計與實現

android上獲取imsi碼,判斷運營商資訊移動,聯通,電信

專案中要用到這個知識點,於是有整理這個知識點,並寫成博文,以作備忘。 一.imsi碼概念的理解 1.概念 IMSI:國際移動使用者識別碼(唯一標識),IMSI = MCC + MNC + MSIN,其中MCC是指移動臺國家程式碼(3 位,中國460),MNC是指移動網程式碼

Android自定義元件之日曆控制元件-精美日曆實現內容、樣式可擴充套件

需求 我們知道,Android系統本身有自帶的日曆控制元件,網路上也有很多開源的日曆控制元件資源,但是這些日曆控制元件往往樣式較單一,API較多,不易於在實際專案中擴充套件並實現出符合具體樣式風格的,內容可定製的效果。本文通過自定義日曆控制元件,實現了在內容和樣