當前位置:首頁 » 操作系統 » androidlauncher2源碼

androidlauncher2源碼

發布時間: 2023-08-13 05:09:05

1. 請教關於make/編譯android源碼中的Launcher2出現錯誤/error41

其實這個問題我也遇到了,不過樓上的方法雖然能解決問題,但是各位有木有相關想過一個問題:每次都要刪除不閑麻煩嗎?為什麼packages/apps/下面的應用我們導入到Eclipse里,一樣的生成了R.java文件,為什麼能夠順利的編譯通過?我覺得:弄清楚了這個問題才算是徹底的解決了樓主提出的問題。

2. 有沒有人分享一下修改launcher的歷程

我自己總結的,ubuntu和windows下幾種不同的修改Launcher的方法:

總共有三大類:
#################
第一類,改簽名:
#################
前面幾個步驟ubuntu和windows通用:
=====================================================================================================
1 eclipse中新建android project,選擇create project from existing source,去android源碼目錄下的packages/apps下找到相應的文件夾。(直接修改的是源碼,所以需要先打包備份一下)然後選擇build target之後finish,可能會等待一段時間。

2 導入完成後,src全是錯誤,由於在Android源碼中,很多方法、成員、類、包都被打上@hide標簽,這些成員在SDK中沒有公開,以至於在編譯Launcher源碼時最常遇到的類android.view.View的成員mScrollX無法訪問
。以Launcher2為例,我們用到的有:(生成的包的路徑為out/target/common/obj/JAVA_LIBRARIES)
1)framework_intermediates/classes.jar :這個主要是android的框架類
2)android-common_intermediates/classes.jar :這個包含com.android.common.Search這個類
3)core_intermediates/classes.jar :這個包包含dalvik.system.VMRuntime這個類
右鍵工程名稱然後選擇Build Path->Configure Build Path...->Libraries->Add Library->User Library->User Libraries...->New...
然後將上面3個依賴的包一個個的加入進來,分別命名為android_framework,android_common,android_core.
將3個包加入進來後,然後還需要將它們放到android2.3.3這個包的前面,可以在Build Path配置中選擇Order and Export
這時候就會發現Launcher2工程以及沒有錯誤了,也可以編譯了。(其他的模塊可能需要別的jar包,都在out/target/common/obj/JAVA_LIBRARIES下能找到).
=====================================================================================================

然後:
===================================================================================================
windows環境下:工程現在是不能直接運行的,因為eclipse默認的debug簽名跟模擬器中的系統簽名不相符合。因此,因此,需要手動簽名。

3 用eclipse導出沒有簽名的版本,右鍵工程,android tools->export unsigned application package,得到未簽名的apk包。

4 在build\target\proct\security下都是一些公鑰和密鑰,system版本的公鑰和密鑰是platform.pk8和platform.x509.pem兩個文件,shared版本的公鑰和密鑰是shared.pk8和shared.x509.pem兩個文件。模塊應用是什麼版本的可以查看AndroidManifest.xml文件,android:sharedUserId="android.uid.system" 表示是system版android:sharedUserId="android.uid.shared"是shared版。除了公鑰密鑰之外,還需要簽名的包即signapk.jar,它在out/host/linux-x86/framework下。

5 將這些工具准備好後,就能打出簽名包了。比如我的為簽名apk是Launcher.apk並且是shared版本。因此java -jar signapk.jar share.x509.pem shared.pk8 Launcher.apk Launcher-signed.apk(system版本就用platform.pk8和platform.x509.pem相應的替換一下)

6 得到了簽名包之後,adb install -r Lancher-signed.apk就行了,直接替換掉原來的Launcher。
=====================================================================================================
ubuntu環境下:利用android源碼提供的工具自動簽名
3 編譯源碼

4 gedit .bashrc 最後面添加
export PATH=$PATH:/home/xxx/android/out/host/linux-x86/bin
export ANDROID_PRODUCT_OUT=/home/xxx/android/out/target/proct/generic
其中的/home/xxx/android是源碼目錄

5 然後啟動模擬器,命令為emulator

6 在eclipse中修改好源碼模塊比如Launcher2之後,將工程放到android源碼目錄下的packages/apps下,刪除掉自動生成的一些文件,比如bin,assets,gen等等。跟其他模塊文件保持一致。

7 android源碼目錄下執行 . build/envsetup.sh 這個時候多出mm,mmm等命令,進入修改過後的那個模塊目錄下,比如packages/apps/Launcher2/下,執行mm,會自動生成已經簽名過的apk文件,放在out/target/proct/generic/system/app下。

8直接adb install -r out/target/proct/generic/system/app/Launcher2.apk即可。

=====================================================================================================
注意:以上的簽名跟源碼相關,如果源碼只是generic的也就是模擬器版,那麼編譯出來的也只能在模擬器上跑,若要在真機上跑,則需要真機的簽名庫,可惜沒有- -,所以需要:

##################
第二類,改包名。
##################

照常理說,應該很簡單,直接在src下的包上F2,然後修改。但是我的機器這個eclipse很奇怪,總有各種問題,現在總結下:
1.導入工程,備份一下AndroidManifest.xml,原因下面有。F2修改包名,修改的時候下面四個選項都選上。

2.修改AndroidManifest.xml
將備份的AndroidManifest.xml換回來,然後ctrl+f,替換全部的原來包名為你現在的,比如之前是com.android.launcher2,現在換成com.pqrs.launcherEx。然後將android:sharedUserId="XXX"這句話刪掉。(這么做的原因是,在第一步中可能已經自動的替換了一些這個xml文件的東西,但是我這eclipse亂七八糟的,缺字或者其他什麼的,此時文件已經損壞了。所以第一步之前,需要備份一下AndroidManifest.xml,在這個步驟中替換回來,然後ctrl+f進行替換。)

3.保存後會有提示,說這個文件變化了,是否作出其他變更,點擊yes。然後res下可能會有一些錯誤,打開那些xml文件,一般都是有些資源引用還是之前的com.android.launcher2,相應的都該成com.pqrs.launcherEx.
比如<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher2">改為<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.pqrs.launcherEx">

4.由於AndroidManifest.xml中的包名改了,gen目錄下的自動生成文件也會跟著變化,但是src下的java文件引用的R文件路徑還沒便過來,還需要更正過來。方法:包名上ctrl+h,選擇file search,在Containing text下輸入之前的import語句,比如是import com.android.launcher2.R;在File name patterns:中填入*.java(表示搜索java文件)scope下選擇Selected resources,然後點擊Replace進行全局替換。

5.如果都順利的話,現在這就是一個新的工程了,直接在eclipse中修改運行即可,而且不限操作系統。

====================================================================================================

#############################################
第三類,網上流傳的,最傳統的方法,只限於ubuntu下。
##############################################

1、建立基本的Android開發環境
請參考官方文檔或<<Android模擬器在Ubuntu8.10的安裝>>

2、編譯Android源碼
Android源碼根目錄下通過make進行編譯,請注意一些配置,具體可參考<<android源碼的編譯>>

3、把eclipse工程配置文件復制到Android源碼根目錄下
cp development/ide/eclipse/.classpath ./
chmod u+w .classpath # Make the writable
4、修改eclipse程序的配置
1)、增大eclipse內存設置
把eclipse.ini(在eclipse軟體的安裝目錄下)的3個值改為下面的值:
-Xms128m
-Xmx512m
-XX:MaxPermSize=256m
2)、把Android-formatting.xml和android.importorder導入eclipse(可選)
Android-formatting.xml、.classpath和android.importorder都放在development/ide/eclipse/下
Android-formatting.xml用來配置eclipse編輯器的代碼風格;android.importorder用來配置eclipse的import的順序和結構。
在window->preferences->java->Code style->Formatter中導入Android-formatting.xml
在window->preferences->java->Code style->Organize Imports中導入Android.importorder
3)、安裝anyedit插件(可選)
在http://andrei.gmxhome.de/anyedit/下載並導入eclipse中

5、把Android源碼作為一個工程導入eclipse
導入前先檢查.classpath里的文件在Android源碼中是否有相應的文件(文件夾),否則也會破壞android源碼(一般是多添加文件/文件夾),.classpath里多餘的路徑可刪除
新建Java Project(不是Android project,否則會破壞android源碼),www.linuxidc.com選擇從已存在的工程導入,工程名任意,完成。
導入時,eclipse要build工程,比較慢。導完後,一般都沒有錯誤。
這里也就回答了第4個問題

6、eclipse上調試Android里的程序。
為了不讓其它版本的Android工具和android文件系統影響下面的編譯和調試,需要從環境變數中去除android工具和android文件系統的路徑:
vim ~/.bashrc
看看有沒有在PATH變數中加入Android工具和android文件系統的路徑,如果加有,則注釋它。通過下面的方法,我們是不需要在.bashrc中添加android工具和android文件系統的路徑的
執行:
cd Android源碼目錄
. build/envsetup.sh #設了環境變數之後,會多出mmm等命令,可以通過輸入help來查看
lunch 1 # 把emulator等工具和ramdisk.img等文件的路徑對應起來,就可以直接調用emulator等工具,也解決了第3個問題
emulator &
ddms &
注意,先啟動ddms,再啟動eclipse,這樣eclipse中就不會說埠沖突
然後在eclipse中配置調試類型和埠:
在Run->Debug Configurations->Remote java application上雙擊,然後,」Host:」設為localhost,」Port:」設為8800,」Connection Type」為Standard(Socket Attach)
然後「Apply」
注意,上面設置的埠要與DDMS中設置的埠一致,ADT插件使用了8700埠,因此上面設置的埠是8800。如果出現連不到VM的錯誤時,請注意,要先在DDMS中選中某一進程(對應某一應用程序),才能在eclipse執行 Debug。
在eclipse調試時,可以設斷點、單步調試。估計google團隊也是這樣開發、調試Android應用程序的

7、編譯Android源碼
執行:
cd Android源碼目錄
. build/envsetup.sh
那 么就會多出mm/mmm等命令,mm/mmm用來編譯模塊(包括C、C++、JAVA程序)。我們也可以直接在 Android源碼根目錄下執行「make 模塊名」來編譯模塊(模塊名可以在.mk文件中找到)。模塊編譯後會在out/target/proct/generic/system/app下生 成對應的.apk包。但是,用mm/mmm來編譯生成的.apk並不會打包到system.img中,需要我們手動通過make snod把 system文件夾打包為system.img,不過這就得重新運行模擬器了,這也是很麻煩了。對於我們開發者來說,我們可以這樣做:
1)把需要修改、調試的模塊(比如AlarmClock.apk)從/system/app下移除,然後make snod,這樣system.img就沒有AlarmClock.apk了。
2)運行模擬器,就看不到AlarmClock了
3)修改AlarmClock源碼並用mm/mmm來編譯,在/system/app下生成AlarmClock.apk
4)通過adb把AlarmClock.apk安裝到Android文件系統中,安裝方法有兩個:
A、通過adb install xxx/AlarmClock.apk
B、通過adb push xxx/AlarmClock.apk /data/app
兩 種方法都可以把 AlarmClock安裝到/data/app下,Android會自動把它顯示在主菜單中(只要AlarmClock.apk中有一Activity包 含android.intent.category.LAUNCHER屬性),不過A方法在/data/app生成 com.android.alarmclock.apk,B方法則是 AlarmClock.apk。用A方法時,如果原來已經安裝了 AlarmClock,你還得先adb uninstall 它,而B方法則不用。推薦使用B方法。同樣,卸載可以通過adb uninstall或adb shell rm xxx/xxx.apk來,也推薦用刪除的方法來卸載

3. 安卓系統桌面循環滾動桌面設置的

1、手機設置」的「輔助功能」中有選擇是否「桌面循環」。
2、在原生的android源碼上添加這一功能。
思路:先把界面做出來,再將是否選擇的值存到系統的(adb shell進入)data/data/com.android.providers.settings/databases/settings.db資料庫中的system表中,
然後在Launch2的源碼中取得資料庫中是否選擇循環桌面來執行相關代碼。
先做UI:
在settings源碼中的accessibility_settings.xml文件中添加一個checkbox:
java代碼
android:key="launch_repeat"
android:title="@string/launch_repeat_title"
android:persistent="false"/>

在settings源碼的res中添加相關的代碼:
在values/string.xml中添加(英文顯示):
Launch Repeat
在values-zh-rCN/string.xml中添加(中文顯示):
"循環桌面"
在settings源碼的AccessibilitySettings.java中的OnCreate中添加:
java代碼
/*****************************************/

mLaunchRepeat=(CheckBoxPreference) findPreference(
LAUNCH_REPEAT);
int LaunchRepeat=Settings.System.getInt(this.getContentResolver(),
"launch_repeat",0);//取出是否被選擇
if(LaunchRepeat==1)//如果被選擇,那麼下次打開setting時就勾選
mLaunchRepeat.setChecked(true);
else
mLaunchRepeat.setChecked(false);//如果沒被選擇,那麼下次打開setting時就不勾選
/*****************************************/
當然還要定義幾個量:
private final String LAUNCH_REPEAT =
"launch_repeat";
private CheckBoxPreference mLaunchRepeat;

在onPreferenceTreeClick函數中添加:
java代碼
//add by xxnan

if(LAUNCH_REPEAT.equals(key))
{
Settings.System.putInt(getContentResolver(),
"launch_repeat",
((CheckBoxPreference) preference).isChecked()?
1:0);//將是否選擇存到系統的system表中
}
//add by xxnan

如果做好了之後當點擊選擇「桌面循環時」可以到(adb shell進入)data/data/com.android.providers.settings/databases下的settings.db資料庫(sqlite3 settings.db)的system
表中看到33|launch_repeat|1(select * from system;)。
到這里就完成了將數據存到系統system表中以及UI,接下來就是在Launch2源碼中去取這個值(是否循環)。
到Launcher2源碼中去找到Workspace.java文件,在裡面有相應的修改:
在onTouchEvent中,之前有修改循環,如下:
java代碼
case MotionEvent.ACTION_UP:

if (mTouchState == TOUCH_STATE_SCROLLING) {
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
final int velocityX = (int)
velocityTracker.getXVelocity(mActivePointerId);
final int screenWidth = getWidth();
final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth;
final float scrolledPos = (float) mScrollX / screenWidth;
Log.i("velocityX","velocityX="+velocityX+"whichScreen="+whichScreen);
/***********************************************/
//modifided by xxnan
if (velocityX > SNAP_VELOCITY) {
// Fling hard enough to move left.
// Don't fling across more than one screen at a time.
Log.i("numscreen","numscreen="+mCurrentScreen);
/* final int bound = scrolledPos < whichScreen ?
( (mCurrentScreen+ getChildCount()) - 1 )% getChildCount():
mCurrentScreen;*/
final int bound =( (mCurrentScreen+ getChildCount()) - 1 )% getChildCount()
;
Log.i("numscreen","bound="+bound);
snapToScreen( bound, velocityX, true);
} else if (velocityX < -SNAP_VELOCITY ) {
// Fling hard enough to move right
// Don't fling across more than one screen at a time.
/*final int bound = scrolledPos > whichScreen ?
( mCurrentScreen + 1 )% getChildCount(): mCurrentScreen;*/
final int bound = ( mCurrentScreen + 1 )% getChildCount() ;
snapToScreen(bound, velocityX, true);
} else {
snapToScreen(whichScreen, 0, true);
}
/***********************************************/
//下面是原生代碼
/*if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
// Fling hard enough to move left.
// Don't fling across more than one screen at a time.
final int bound = scrolledPos < whichScreen ?
mCurrentScreen - 1 : mCurrentScreen;
snapToScreen(Math.min(whichScreen, bound), velocityX, true);
} else if (velocityX < -SNAP_VELOCITY && mCurrentScreen <
getChildCount() - 1) {
// Fling hard enough to move right
// Don't fling across more than one screen at a time.
final int bound = scrolledPos > whichScreen ?
mCurrentScreen + 1 : mCurrentScreen;
snapToScreen(Math.max(whichScreen, bound), velocityX, true);
} else {
snapToScreen(whichScreen, 0, true);
}*/
}
mTouchState = TOUCH_STATE_REST;
mActivePointerId = INVALID_POINTER;
releaseVelocityTracker();
break;

那麼就要在修改的地方加一個判斷,如果system中取得的值是1,就可以循環,如果是0,就不能。
代碼修改如下:
java代碼
case MotionEvent.ACTION_UP:

if (mTouchState == TOUCH_STATE_SCROLLING) {
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
final int velocityX = (int)
velocityTracker.getXVelocity(mActivePointerId);
final int screenWidth = getWidth();
final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth;
final float scrolledPos = (float) mScrollX / screenWidth;
Log.i("velocityX","velocityX="+velocityX+"whichScreen="+whichScreen);
/***********************************************/
//modifided by xxnan 2013-1-9
launch_repeat=Settings.System.getInt(mContext.getContentResolver(),
"launch_repeat",0);//取出system表中「launch_repeat」的值
Log.i(" launch_repeat"," launch_repeat="+ launch_repeat);
if(launch_repeat==1)//如果是1,就循環,也就是之前已經改好的
{
if (velocityX > SNAP_VELOCITY) {
// Fling hard enough to move left.
// Don't fling across more than one screen at a time.
Log.i("numscreen","numscreen="+mCurrentScreen);
/* final int bound = scrolledPos < whichScreen ?
( (mCurrentScreen+ getChildCount()) - 1 )% getChildCount():
mCurrentScreen;*/
final int bound =( (mCurrentScreen+ getChildCount()) - 1 )% getChildCount()
;
Log.i("numscreen","bound="+bound);
snapToScreen( bound, velocityX, true);
} else if (velocityX < -SNAP_VELOCITY ) {
// Fling hard enough to move right
// Don't fling across more than one screen at a time.
/*final int bound = scrolledPos > whichScreen ?
( mCurrentScreen + 1 )% getChildCount(): mCurrentScreen;*/
final int bound = ( mCurrentScreen + 1 )% getChildCount() ;
snapToScreen(bound, velocityX, true);
} else {
snapToScreen(whichScreen, 0, true);
}
}
else//如果是0,那麼就是原生代碼,不循環
{
if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
// Fling hard enough to move left.
// Don't fling across more than one screen at a time.
final int bound = scrolledPos < whichScreen ?
mCurrentScreen - 1 : mCurrentScreen;
snapToScreen(Math.min(whichScreen, bound), velocityX, true);
} else if (velocityX < -SNAP_VELOCITY && mCurrentScreen <
getChildCount() - 1) {
// Fling hard enough to move right
// Don't fling across more than one screen at a time.
final int bound = scrolledPos > whichScreen ?
mCurrentScreen + 1 : mCurrentScreen;
snapToScreen(Math.max(whichScreen, bound), velocityX, true);
} else {
snapToScreen(whichScreen, 0, true);
}
}
/***********************************************/
//下面是原生代碼
/*if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
// Fling hard enough to move left.
// Don't fling across more than one screen at a time.
final int bound = scrolledPos < whichScreen ?
mCurrentScreen - 1 : mCurrentScreen;
snapToScreen(Math.min(whichScreen, bound), velocityX, true);
} else if (velocityX < -SNAP_VELOCITY && mCurrentScreen <
getChildCount() - 1) {
// Fling hard enough to move right
// Don't fling across more than one screen at a time.
final int bound = scrolledPos > whichScreen ?
mCurrentScreen + 1 : mCurrentScreen;
snapToScreen(Math.max(whichScreen, bound), velocityX, true);
} else {
snapToScreen(whichScreen, 0, true);
}*/
}
mTouchState = TOUCH_STATE_REST;
mActivePointerId = INVALID_POINTER;
releaseVelocityTracker();
break;

當然這裡面也要定義幾個量,以及導入幾個包:
導入包:
//add by xxnan
import android.content.ContentResolver;//從system表中取數據
import android.provider.Settings;
定義變數:
private int launch_repeat;//取得是否循環的值
到這里就全部修改好了,還有就是編譯一下源碼中的package/apps的Launch2和Settings的源碼,將生成的out/target/。。。/system/app下的
Launch2.apk和Settings.apk替換手機里system/app的這兩個apk就可以了。

4. 自己可以編譯安卓源碼嗎

用最新的Ubuntu 16.04,請首先確保自己已經安裝了Git.沒安裝的同學可以通過以下命令進行安裝:

sudo apt-get install git git config –global user.email 「[email protected]」 git config –global user.name 「test」

其中[email protected]為你自己的郵箱.

簡要說明

android源碼編譯的四個流程:1.源碼下載;2.構建編譯環境;3.編譯源碼;4運行.下文也將按照該流程講述.

源碼下載

由於某牆的原因,這里我們採用國內的鏡像源進行下載.
目前,可用的鏡像源一般是科大和清華的,具體使用差不多,這里我選擇清華大學鏡像進行說明.(參考:科大源,清華源)

repo工具下載及安裝

通過執行以下命令實現repo工具的下載和安裝

mkdir ~/binPATH=~/bin:$PATHcurl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repochmod a+x ~/bin/repo

補充說明
這里,我來簡單的介紹下repo工具,我們知道AOSP項目由不同的子項目組成,為了方便進行管理,Google採用Git對AOSP項目進行多倉庫管理.在聊repo工具之前,我先帶你來聊聊多倉庫項目:

我們有個非常龐大的項目Pre,該項目由很多個子項目R1,R2,...Rn等組成,為了方便管理和協同開發,我們為每個子項目創立自己的倉庫,整個項目的結構如下:


這里寫圖片描述

執行完該命令後,再使用make命令繼續編譯.某些情況下,當你執行jack-admin kill-server時可能提示你命令不存在,此時去你去out/host/linux-x86/bin/目錄下會發現不存在jack-admin文件.如果我是你,我就會重新repo sync下,然後從頭來過.

錯誤三:使用emulator時,虛擬機停在黑屏界面,點擊無任何響應.此時,可能是kerner內核問題,解決方法如下:
執行如下命令:

  • ./out/host/linux-x86/bin/emulator -partition-size 1024 -kernel ./prebuilts/qemu-kernel/arm/kernel-qemu-armv7

  • 通過使用kernel-qemu-armv7內核 解決模擬器等待黑屏問題.而-partition-size 1024 則是解決警告: system partion siez adjusted to match image file (163 MB >66 MB)

    如果你一開始編譯的版本是aosp_arm-eng,使用上述命令仍然不能解決等待黑屏問題時,不妨編譯aosp_arm64-eng試試.

    結束吧

    到現在為止,你已經了解了整個android編譯的流程.除此之外,我也簡單的說明android源碼的多倉庫管理機制.下面,不妨自己動手嘗試一下.

    5. android源碼中有launcher2launcher3,用的是哪個

    1、Launcher進程啟動過程
    可以由下面圖看到Launcher進程是如何被創建啟動:

    Activity Manager通過發送Intend來啟動Launcher。
    Intent intent = new Intent(mTopAction, mTopData != null ?

    Uri.parse(mTopData) : null);

    intent.setComponent(mTopComponent);

    if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL)

    {

    intent.addCategory(Intent.CATEGORY_HOME);

    }

    startActivityLocked(null, intent, null, null, 0, aInfo,

    null, null, 0, 0, 0, false, false);
    復制代碼
    因此,如果你要開機啟動一個替換Launcher的程序,只要在程序<intent-filter>裡面加入action.MAIN 、
    category.HOME、category.DEFAULT就可以。如果出現多個程序都加入這種intent,系統會彈出讓你選擇
    哪個作為啟動器。

    2、Launcher初始化——LauncherApplication。
    Application類,我想大部分做Android應用的朋友都用過,每個Android應用默認都有一個Application類,
    你也可以繼承Application類,然後加入自己代碼。Application是一個全局的應用類,在AndroidManifest.xml
    我們也可以找到Application標簽。

    <application

    android:name="com.android.launcher2.LauncherApplication"

    android:label="@string/application_name"

    android:icon="@drawable/ic_launcher_home"

    android:hardwareAccelerated="@bool/config_hardwareAccelerated"

    android:largeHeap="@bool/config_largeHeap"

    android:configChanges="locale">

    </application>
    復制代碼
    Android四大組件的聲明都需要放到application標簽裡面,默認使用的是系統的Application類,如果你在項目裡面重載了它。就需要在標簽,name屬性下寫上你的新的Application類名。Launcher裡面就是繼承了Application為LauncherApplication。應用啟動的時候首先會載入Application。我們可以看到Launcher主類Launcher.java的onCreate函數裡面,第一個就是獲取Application的實例。
    LauncherApplication app = ((LauncherApplication)getApplication());
    復制代碼
    接下來我們看看LauncherApplication裡面初始化,LauncherApplication大部分工作就是在初始化完成,剩下都是一些返回介面。
    @Override

    public void onCreate()

    {

    super.onCreate();

    //獲取屏幕大小,主要用來區分手機還是平板

    final int screenSize = getResources().getConfiguration().screenLayout &

    Configuration.SCREENLAYOUT_SIZE_MASK;

    sIsScreenLarge = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE ||

    screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE;

    //屏幕密度

    sScreenDensity = getResources().getDisplayMetrics().density;

    //IconCahe裡面保存了界面所有應用圖標的繪畫需要的數據,這個到時候具體分析再說。

    //加入這東西的主要原因是為了提高繪畫界面的效率

    mIconCache = new IconCache(this);

    //資料庫載入類,LauncherModel是Launcher裡面非常重要的一個類,相當於MVC模式裡面的

    //Model功能,管理數據和初始化數據

    mModel = new LauncherModel(this, mIconCache);

    //下面注冊了一些監聽器,主要包含APK文件更新刪除等數據變化的時候接收的通知

    //接收通知後,主要是用來更新Launcher裡面的資料庫。因為桌面應用圖標數據,只會載入一次

    IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);

    filter.addAction(Intent.ACTION_PACKAGE_REMOVED);

    filter.addAction(Intent.ACTION_PACKAGE_CHANGED);

    filter.addDataScheme("package");

    registerReceiver(mModel, filter);

    filter = new IntentFilter();

    filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);

    filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);

    filter.addAction(Intent.ACTION_LOCALE_CHANGED);

    filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);

    registerReceiver(mModel, filter);

    filter = new IntentFilter();

    filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);

    registerReceiver(mModel, filter);

    filter = new IntentFilter();

    filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);

    registerReceiver(mModel, filter);

    //contentresolver則是用於管理所有程序的contentprovider實例

    ContentResolver resolver = getContentResolver();

    //注冊內容觀察者,監聽application資料庫變化,回調

    resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true, mFavoritesObserver);

    }
    復制代碼
    上面是LauncherApplication最主要的工作,初始化整個Launcher的一些關鍵類,和注冊一些監聽器。主要都是用來監聽應用的安裝更新刪除等導致Launcher資料庫變化的操作。Launcher數據都是使用contentprovider來提供數據。其中注冊的監聽介面是
    private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler())

    {

    @Override

    public void onChange(boolean selfChange)

    {

    //重新載入界面數據

    mModel.startLoader(LauncherApplication.this, false);

    }

    };
    復制代碼
    LauncherSettings.Favorites.CONTENT_URI裡面數據發生變化的時候,都會調用mModel.startLoader()介面,
    重新載入Launcher的數據。startLoader的具體操作,我後面分析LauncherModel類的時候會分析。這一塊涉及
    Launcher所有數據載入。剩下的接都是返回初始化時候創建的對象或者獲取屏幕密度、獲取是否大屏幕。
    後面很多處理都需要判斷是否是大屏幕,4.0以後手機平板都共用一套系統,導致多了很多處理。 3、Launcher.java初始化Launcher.java是Launcher裡面最主要的類,是一個Activity。啟動的第一個組件。既然是Activity,我們要分析它初始化,毫無疑問,需要找到onCreate()裡面分析。把主要一些分析用注釋方式寫在代碼裡面,這樣比較方便閱讀。

    6. 怎樣查看 Android APP 源代碼

    壓縮軟體打開apk文件,解壓出根目錄中的classes.dex文件

    使用cmd ,dex2jar.bat classes.dex命令將classes.dex轉換為jar

    再用jd-gui打開該jar就可以查看源碼了,如果apk安全性好的話,有些代碼是看不到的

    7. 怎樣查看 Android APP源代碼

    將apk文件拷貝至sdcard上。
    命令順序如下:

    進入Android sdk文件夾/tools目錄下
    輸入adb shell
    輸入su
    輸入cd data
    輸入cd app
    這時就可以看到你安裝的所有的apk文件。輸入cp 空格 對應的apk 空格 /sdcard/
    這樣就將apk文件拷貝出來了。
    將apk文件後綴直接變成rar格式,可以看到熟悉的目錄結構了,

    其中xml文件打開後都是二進制的,無法查看。
    這時就用到了一個android4me的AXMLPrinter2工具。(請自行網路搜索)
    輸入以下命令,將xml文件解析出來
    java -jar AXMLPrinter2.jar showtimes_list.xml
    此命令是在命令行中查看此showtimes_list.xml
    將showtimes_list.xml生成xml文件,則輸入以下命令:
    java -jar AXMLPrinter2.jar showtimes_list.xml > h.xml
    目前進行到這一步,只能看到xml文件的內容,其工程中的java源文件還是看不到,看目錄結構下有一個classes.dex文件,我們需要將dex文件變為jar文件。
    這里用到了另一個工具dex2jar。(自行搜索下載)
    在Windows下解壓之後的目錄如下圖所示:

    在命令行中,進入到此目錄下:
    在Windows下,輸入以下命令:
    dex2jar.bat c:classes.dex
    運行完之後,在C盤會多一個classes.dex.dex2jar.jar文件,此文件就是我們需要的jar文件。
    利用jd-gui,將jar文件反向工程為java代碼。(請自行搜索下載)
    它分為Windows、Linux、和max三個版本,這里我下載的是Windows版本的。
    解壓之後,雙擊運行exe文件,選擇classes.dex.dex2jar.jar文件,相應的jar文件中的Java文件就被反向工程顯示出來了!

    8. android怎麼修改源碼

    在Android界面的系統status bar上添加home,back,menu三個菜單,並完成對應的系統功能。並有higlight效果,修改status bar 高度和status bar上的文字尺寸。

    這需要修改android sdk才能完成,我用的是eclair.下面就我的操作進行敘述。

    1.首先完成界面顯示效果。

    需要修改文件

    ./frameworks/base/services/java/com/android/server/status/StatusBarPolicy.java,仿照mBatteryIcon等icon的添加方式添加自定義的icon,圖片名稱指定就好了。另外還要記得修改./frameworks/base/core/res/res/values/arrays.xml,這里定義了icon的slot,並且決定了icon的擺放順序。

    這樣,你需要的icon按鍵就可以顯示在系統的status bar上面了。

    2.判斷touch event是否按動了某個icon

    需要修改的文件

    ./frameworks/base/services/java/com/android/server/status/StatusBarView.java

    首先在onTouchEvent函數中,獲取當前event的坐標,然後比較是否在某個按鍵范圍之內。由於系統對於statusBar的范圍已經有了定義,所以這里只需要比較橫坐標就可以了。

    其次,也是這一步最關鍵的,怎麼獲取具體某一個icon的左右邊界坐標呢?系統的status bar左邊顯示的圖標都是notification, 右邊顯示的是系統icon. 也就是說左邊icon屬於mNotificationIcons,右邊的icon屬於mStatusIcons. 在文件StatusBarView.java中出現的offset = getViewOffset(mStatusIcons),得到mStatusIcons的最左邊的icon的left橫坐標。用N = mStatusIcons.getChildCount()得到共有幾個系統icon,其中包含visibility為false的icons.用mStatusIcons.getChildAt(N-i)得到的是從右邊數第i個的icon view. 這個view的getLeft()+offset就是這第i個icon的左邊橫坐標,對應的getRight()+offset就是這第i個icon的右邊橫坐標。本例中home鍵是右邊第2個icon.

    3.定義icon響應事件

    這里使用的方法是在StatusBarView.java中向

    ./frameworks/base/services/java/com/android/server/status/StatusBarPolicy.java發送一個Broadcast,讓StatusBarPolicy來完成具體的事件操作。這里需要注意的是不僅要在./frameworks/base/core/java/android/content/Intent.java中定義intent,還要在StatusBarPolicy的構造函數中添加該intent的過濾動作,即filter.addAction(Intent.ACTION_BACKICON_CHANGED).例如,按動了back鍵,如果當前事件為action_up,就向系統發送一個keyEvent,keyCode為KeyEvent.KEYCODE_BACK. 這里借用的是./frameworks/base/cmds/input/src/com/android/commands/input/Input.java中的sendKeyEvent函數,直接拷貝過來,按照需要稍微修改一下形參就可以了,過程不要修改。

    需要說明的是,當點擊statusBar可以拉出來一個notification列表,當這個列表顯示出來的時候,這三個back, menu, home鍵的響應速度會非常慢,所以這時不響應事件並隱藏這三個鍵。具體做法是在StatusBarView的onTouchEvent()中判斷mService.mExpanded或者 mService.mTracking為真時就不做響應。mService是StatusBarService對象。隱藏三個鍵也是用Broadcast來做的,但這個intent是由StatusBarServie發出來的,當mExpandedVisible = false時顯示,當mExpandedVisible = true時隱藏。

    這里還同時完成了highlight換圖的動作,也是用Broadcast來做得,處理過程一樣,就是需要區分action_down和action_up就可以了。

    4.調整status bar的高度

    如果你需要顯示較大的屏幕尺寸,同時statusBar的高度要拉大,上面的icon的size也需要調大。為了協調一致,顯示時間的字體和notification顯示的日期的字體也需要調大。具體做法如下:

    a.調節status bar icon的size: 只調節status_bar.xml的textSize標簽似乎不起作用,同時又修改了./base/services/java/com/android/server/status/StatusBarIcon.java的t.setTextSize(32);語句才成功。不知道修改status_bar.xml的<com.android.server.status.AnimatedImageView>標簽下的layout_height值是不是必須的,反正我是一起都給改了。

    b.調節status bar height: ./base/core/res/res/values/dimens.xml 找得我好辛苦!不知道還需不需要修改./base/core/res/res/values/themes.xml中的Window attributes的windowTitleSize值,反正我也給改了。

    c.調節notification顯示日期字體的大小,修改status_bar.xml的<com.android.server.status.DateView>的textSize值。

    到這里,就完成了所有工作,看看效果吧。

    熱點內容
    網易我的世界如何登陸伺服器 發布:2025-03-11 06:23:22 瀏覽:713
    用電腦玩逆戰連接伺服器很久 發布:2025-03-11 06:13:18 瀏覽:181
    天翼智能路由器的初始密碼是多少 發布:2025-03-11 06:10:17 瀏覽:914
    安卓機怎麼領嶺南通 發布:2025-03-11 05:56:54 瀏覽:132
    求生之路2虐電腦伺服器 發布:2025-03-11 05:35:40 瀏覽:632
    編譯學堂 發布:2025-03-11 05:31:06 瀏覽:185
    蘋果文件夾隱藏 發布:2025-03-11 05:26:42 瀏覽:546
    簡訊設置密碼如何關閉 發布:2025-03-11 05:26:39 瀏覽:915
    re管理器主文件夾 發布:2025-03-11 05:26:37 瀏覽:714
    手機優酷緩存在哪 發布:2025-03-11 05:25:58 瀏覽:434