android啟動參數
㈠ android模擬器中命令參數主要有哪些
1、Help
-help列印模擬器參數列表。
-help-all列印所有啟動參數明細。
-help-<option>列印指定啟動參數的信息。
-help-debug-tags列印所有被-debug <tags>打開的列表。
-help-disk-images列印正在使用的磁碟鏡像信息。
-help-environment列印模擬器環境變數信息。
-help-keys列印當前的鍵盤映射。
-help-keyset-file列印一個自定義的鍵盤映射文件的定義。
2、Disk Images
-cache <filepath>使用<filepath> 指定網路緩存分區鏡像。自定義,您可以指定一個當前工作目錄的相對路徑。如果沒有指定緩存文件,模擬器會指定一個零時文件作為緩存文件。
-data <filepath>使用<filepath>作為用戶數據磁碟鏡像。自定義,您可以指定一個當前工作目錄的相對路徑。如果-data沒有被使用,模擬器會在<datadir>指定的目錄下尋找名叫"userdata-qemu.img"的鏡像文件。默認情況下,模擬器會尋找~/.android (on linux/Mac)或者C:/Documents and Settings/<user>/Local Settings/Application Data/Android (on Windows)。如果您使用了-data <filepath>,但是文件並不存在,模擬器將創建同名文件。
-image <filepath>使用<filepath>作為系統鏡像。自定義,您可以指定一個當前工作目錄的相對路徑。默認為<system>/system.img。
-initdata <filepath>重寫用戶數據鏡像時,(使用 -wipe-data),復制此文件內容到新用戶數據文件鏡像中。默認方式下,模擬器拷貝<system>/userdata.img。自定義,您可以指定一個當前工作目錄的相對路徑。
-kernel <filepath>使用<filepath>作為模擬器內核。自定義,您可以指定一個當前工作目錄的相對路徑。
-nocache啟動模擬器時無緩存分區。
-ramdisk <filepath>使用<filepath>作為虛擬內存鏡像。默認<system>/ramdisk.img. 自定義,您可以指定一個當前工作目錄的相對路徑。
-sdcard <filepath>使用<file>作為SD卡鏡像。默認為<system>/sdcard.img. 自定義,您可以指定一個當前工作目錄的相對路徑。
-system <dirpath>在指定的<dir>下搜索系統、虛擬內存和用戶數據鏡像文件。<dir>為當前路徑的相對目錄。
-wipe-data重至用戶數據鏡像文件。(that is, the file specified by -datadir and -data, or the default file)。 模擬器刪除所有用戶數據,然後復制右-inidata參數指定的數據到鏡像文件,在啟動之前。
3、Debug
-debug <tags>開啟/關閉指定tag的調試信息。
<tags>是一個被空格/逗號/縱列所分割的調試組建名稱列表。
-debug-<tag>開啟/關閉指定tag的調試信息。使用-help-debug-tags獲得您可以指定為<tag>的調試組件列表。
-debug-no-<tag>關閉指定tag的調試信息。
-logcat <logtags>打開指定tag的日誌輸出。如果環境變數ANDROID_LOG_TAGS被指定且不為空,她的值將成為日誌輸出的默認值。
-shell創建一個擁有root許可權的命令行窗口。即使模擬器的UI界面無法使用了,您依然可以使用命令行窗口。按Ctr-c鍵中斷模擬器運行。
-shell-serial <device>打開具有root許可權的腳本窗口。<device>必須是一個QEMU類型的設備。
-show-kernel <name>顯示內核信息。
-trace <name>Enable code profiling (press F9 to start), written to a specified file.
-verbose開啟冗長輸出。Equivalent to -debug-init. 您可以定義ANDROID_VERBOSE環境變數作為冗長輸出參數。定義你想用到的參數,用逗號分割。這樣可以省略像-debug-<tags>這樣的參數。
4、Media
-audio <backend>使用指定的音頻後端。
-audio-in <backend>使用指定的音頻輸入後端。
-audio-out <backend>使用指定的音頻輸出後端。
-noaudio在當前虛擬機實例中關閉音頻支持。
-radio <device>重新定向收音機介面到本地的位元組設備。
-useaudio打開模擬器實例的音頻支持。默認狀態為打開。
5、Network
-dns-server <servers>使用指定的DNS伺服器。<servers>必須是以逗號分割,多於4個的伺服器名或IP地址。
-http-proxy <proxy>配置TCP連接使用HTTP/HTTPS代理。
<proxy>必須符合以下格式:http://<server>:<port>
http://<username>:<password>@<server>:<port> 前綴http://可以被忽略。如果-http-proxy <proxy>未被指定,模擬器將尋找http_proxy環境變數,並且自動尋找所有符號格式要求的<proxy> 值。
-netdelay <delay>設置網路延遲默認值為none。
-netfast快捷的 -netspeed full -netdelay none
-netspeed <speed>指定模擬器網路速度為<speed>,默認值為full。
-port <port>指定模擬器網路埠為<port>,控制台埠號必須介於5554和5584之間,並且<port>+1必須留作ADB使用。
-report-console <socket>啟動前向第三方同志此模擬器實例的網路埠。<socket> 必須是以下幾種格式:
tcp:<port>[,server][,max=<seconds>]
unix:<port>[,server][,max=<seconds>]
6、System
-cpu-delay <delay>降低模擬器CPU的速度到<delay>。<delay>支持0到100的整數。注意<delay>與具體的時鍾或其他的絕對頻率無關。它只表現為一種抽象的,相對於當前模擬器運行狀況的速度調節。
-gps <device>重定向NMEA GPS到位元組設備。
使用此參數通知模擬器模擬一個NMEA-compatible GPS,連接到一個擴展的設備或socket埠。<device>格式必須符合QEMU-specific所指定的設備格式。
-nojni在Dalvik運行時關閉JNI檢查
-qemu傳遞參數到qemu。
-qemu -h關閉qemu幫助。
-radio <device>重定向錄音機模塊到制定的字元設備。<device>格式必須符合QEMU規定的序列設備。
-timezone <timezone>設定模擬器時區為<timezone>,替換為系統時區。<timezone>必須按照時區格式指定。比如:"America/Los_Angeles","Europe/Paris"
-version顯示模擬器版本號。
7、UI
-dpi-device <dpi>修改模擬器的解析度適配物理設備。默認值為165。參見-scale.
-no-boot-anim關閉模擬器啟動時的動畫。禁用啟動動畫可以加快啟動速度。
-no-window關閉模擬器的繪制窗口。
-scale <scale>調整模擬器窗口。<scale> 是介於0.1到3的數字,它是調整屏幕的比例因子。您也可以指定一個DPI值,在添加dpi前綴的情況下。Auto參數告訴模擬器選擇自己最合適的尺寸。
-raw-keys關閉Unicode鍵盤reverse-mapping.
-noskin不使用任何模擬器皮膚。
-keyset <file>用指定的鍵盤設置文件代替默認。指定宿主鍵盤和模擬器之間的鍵盤映射文件。
-onion <image>用圖片覆蓋屏幕。不支持JPEG,只支持PNG。
-onion-alpha <percent>指定onion皮膚透明值(百分比) 默認為50.
-onion-rotation <position>指定onion皮膚旋轉。<position> 必須是 0, 1, 2, 3中的一個。
-skin <skinID>啟動模擬器,搭配指定皮膚。
-skindir <dir>在指定目錄<dir>下搜索皮膚
以上就是android模擬器中的一些常用參數及其作用,可能還有整理得不夠全面得地方,歡迎大家補充分享。
㈡ Android 啟動流程
makeApplication創建application中會執行attachBaseContext(context);
installContentProviders第一個參數context,是從上面傳遞下來的app,也就是application。
遍歷providers列表,初始化每一個provider,都是用application的context。構造出ContentProvider然後執行attachInfo() 方法,attachInfo()執行完畢會執行onCreate()。
最後再mInstrumentation.callApplicationOnCreate(app);執行Application的OnCreate方法。
總結
從流程上來看,符合日誌列印的流程Application#attachBaseContext() → ContentProvider#attachInfo() → ContentProvider#onCreate() → Application#onCreate()
ContentProvider持有的Context也是application,具備給SDK初始化使用。
這時候第一進程是zygote。zygote英文是受精卵的意思。android系統的所有進程都是由zygote進程fork而來。zygote最先啟動的第一個進程是鼎鼎大名的SystemServer進程。這個進程包含了我們常說的三個大神級系統服務,分別是ActivityManagerService,WindowManagerService以及PackegeManagerService。
http://androidxref.com/6.0.0_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java
進程入口在ActivityThread這個類的main()方法,這個main方法類似C語言的mian方法,是一個程序入口。
這個方法會接著調用ActivityManagerNatvie(一個單例類,可以獲取ActivityManagerService的實例)的getDeafault()返回ActivityManagerService實例。
ApplicationThread是ActivityThread的內部類,他是App和系統跨進程交互的入口,它的實現類在客戶端進程。
獲得了正在Binder通信的客戶端的當前線程的id,然後和ApplicationThread對象作為參數傳入到AMS的attachApplicationLocked。
thread是ApplicationThreadProxy的對象引用,它是代理對象,先調用ApplicationThreadProxy的bindApplication方法,接著在這個方法中又調用ApplicationThreadNative的函數onTransact,然後函數onTransact中根據code找到對應的case,最終會調用ApplicationThread的bindApplication方法。
在這里,bindApplication方法通過向ActivityThread的消息隊列發送BIND_APPLICATION消息
消息的處理調用handleBindApplication方法,handleBindApplication方法比較重要的是會調用如下方法
在執行完bindApplication()之後進入ActivityStackSupervisor.attachApplicationLocked(),這樣我們整個應用進程已經啟動起來了。開始activity的啟動邏輯了。
這個類是一個AMS的一個棧管理類,裡面存儲著ActivityStack的集合。在這個方法,會遍歷各個ActivityStack,找到前台棧,找到裡面的TopActivity。然後比較 傳進來的ProcessRecord.processName和UID是否個和opActivity對用的ActivityRecord裡面的一致。如果一致,就調用ActivityStackSupervisor.realStartAcvitiyLocked(ProcessRecord,ActivityRecord)方法。
這個方法會調用傳過來的ApplicationThread實例的ScheelLaunchActivity(包括ActivityRecord)方法,所以真正執行的是ActivityThread中的scheleLaunchActivity
這個方法是跨進程的,會把ActivityRecord同步到App進程的ActivityRecordClient數據結構,用來後面構造Application和Activity等。
ActivityThread接收到SystemServer進程的消息之後會通過其內部的Handler對象分發消息,經過一系列的分發之後調用了ActivityThread的handleLaunchActivity方法:
接著調用PerformLaunchActivity方法和HandleLaunchActivtiy()方法。performLauncherActivity,看名字應該就是執行Activity的啟動操作了
1.這個方法主要是構造Application和通過mInstrumention.newActivity()構造Activity。
這個方法會初始化一個Window,以後詳細講,人格視圖都是附在一個window的docorView上,然後由WMS.addView顯示。
這個方法會調用Actiity的resume()方法,並且在makrVisible()裡面調用WMS.addView(window),這個windows裡面的docorView的contentView就是onCreate()裡面setContentView(int layout)設置的contentView。
注意關於WMS.addView(window),這個系統服務,我們下次再講,裡面有一個類RootViewImpl,這個類負責管理我們contentView視圖樹的逐級繪制。
原文鏈接
https://www.cnblogs.com/mingfeng002/p/10330414.html
https://blog.csdn.net/ZZB_Bin/article/details/125209192
㈢ Android啟動過程深入解析
當按下Android設備電源鍵時究竟發生了什麼?
Android的啟動過程是怎麼樣的?
什麼是Linux內核?
桌面系統linux內核與Android系統linux內核有什麼區別?
什麼是引導裝載程序?
什麼是Zygote?
什麼是X86以及ARM linux?
什麼是init.rc?
什麼是系統服務?
當我們想到Android啟動過程時,腦海中總是冒出很多疑問。本文將介紹Android的啟動過程,希望能幫助你找到上面這些問題的答案。
Android是一個基於Linux的開源操作系統。x86(x86是一系列的基於intel 8086 CPU的計算機微處理器指令集架構)是linux內核部署最常見的系統。然而,所有的Android設備都是運行在ARM處理器(ARM 源自進階精簡指令集機器,源自ARM架構)上,除了英特爾的Xolo設備(http://xolo.in/xolo-x900-features)。Xolo來源自凌動1.6GHz x86處理器。Android設備或者嵌入設備或者基於linux的ARM設備的啟動過程與桌面版本相比稍微有些差別。這篇文章中,我將解釋Android設備的啟動過程。深入linux啟動過程是一篇講桌面linux啟動過程的好文。
當你按下電源開關後Android設備執行了以下步驟。
此處圖片中step2中的一個單詞拼寫錯了,Boot Loaeder應該為Boot Loader(多謝@jameslast 提醒)
第一步:啟動電源以及系統啟動
當電源按下,引導晶元代碼開始從預定義的地方(固化在ROM)開始執行。載入引導程序到RAM,然後執行。
第二步:引導程序
引導程序是在Android操作系統開始運行前的一個小程序。引導程序是運行的第一個程序,因此它是針對特定的主板與晶元的。設備製造商要麼使用很受歡迎的引導程序比如redboot、uboot、qi bootloader或者開發自己的引導程序,它不是Android操作系統的一部分。引導程序是OEM廠商或者運營商加鎖和限制的地方。
引導程序分兩個階段執行。第一個階段,檢測外部的RAM以及載入對第二階段有用的程序;第二階段,引導程序設置網路、內存等等。這些對於運行內核是必要的,為了達到特殊的目標,引導程序可以根據配置參數或者輸入數據設置內核。
Android引導程序可以在找到。
傳統的載入器包含的個文件,需要在這里說明:
init.s初始化堆棧,清零BBS段,調用main.c的_main()函數;
main.c初始化硬體(鬧鍾、主板、鍵盤、控制台),創建linux標簽。
更多關於Android引導程序的可以在這里了解。
第三步:內核
Android內核與桌面linux內核啟動的方式差不多。內核啟動時,設置緩存、被保護存儲器、計劃列表,載入驅動。當內核完成系統設置,它首先在系統文件中尋找」init」文件,然後啟動root進程或者系統的第一個進程。
第四步:init進程
init是第一個進程,我們可以說它是root進程或者說有進程的父進程。init進程有兩個責任,一是掛載目錄,比如/sys、/dev、/proc,二是運行init.rc腳本。
init進程可以在/system/core/init找到。
init.rc文件可以在/system/core/rootdir/init.rc找到。
readme.txt可以在/system/core/init/readme.txt找到。
對於init.rc文件,Android中有特定的格式以及規則。在Android中,我們叫做Android初始化語言。
Action(動作):動作是以命令流程命名的,有一個觸發器決定動作是否發生。
語法
1
2
3
4
5
; html-script: false ]
on <trigger>
<command>
<command>
<command>
Service(服務):服務是init進程啟動的程序、當服務退出時init進程會視情況重啟服務。
語法
1
2
3
4
5
; html-script: false ]
service <name> <pathname> [<argument>]*
<option>
<option>
...
Options(選項)
選項是對服務的描述。它們影響init進程如何以及何時啟動服務。
咱們來看看默認的init.rc文件。這里我只列出了主要的事件以及服務。
Table
Action/Service
描述
on early-init
設置init進程以及它創建的子進程的優先順序,設置init進程的安全環境
on init
設置全局環境,為cpu accounting創建cgroup(資源控制)掛載點
on fs
掛載mtd分區
on post-fs
改變系統目錄的訪問許可權
on post-fs-data
改變/data目錄以及它的子目錄的訪問許可權
on boot
基本網路的初始化,內存管理等等
service servicemanager
啟動系統管理器管理所有的本地服務,比如位置、音頻、Shared preference等等…
service zygote
啟動zygote作為應用進程
在這個階段你可以在設備的屏幕上看到「Android」logo了。
第五步
在Java中,我們知道不同的虛擬機實例會為不同的應用分配不同的內存。假如Android應用應該盡可能快地啟動,但如果Android系統為每一個應用啟動不同的Dalvik虛擬機實例,就會消耗大量的內存以及時間。因此,為了克服這個問題,Android系統創造了」Zygote」。Zygote讓Dalvik虛擬機共享代碼、低內存佔用以及最小的啟動時間成為可能。Zygote是一個虛擬器進程,正如我們在前一個步驟所說的在系統引導的時候啟動。Zygote預載入以及初始化核心庫類。通常,這些核心類一般是只讀的,也是Android SDK或者核心框架的一部分。在Java虛擬機中,每一個實例都有它自己的核心庫類文件和堆對象的拷貝。
Zygote載入進程
載入ZygoteInit類,源代碼:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
registerZygoteSocket()為zygote命令連接注冊一個伺服器套接字。
preloadClassed 「preloaded-classes」是一個簡單的包含一系列需要預載入類的文本文件,你可以在/frameworks/base找到「preloaded-classes」文件。
preloadResources() preloadResources也意味著本地主題、布局以及android.R文件中包含的所有東西都會用這個方法載入。
在這個階段,你可以看到啟動動畫。
第六步:系統服務或服務
完成了上面幾步之後,運行環境請求Zygote運行系統服務。系統服務同時使用native以及java編寫,系統服務可以認為是一個進程。同一個系統服務在Android SDK可以以System Services形式獲得。系統服務包含了所有的System Services。
Zygote創建新的進程去啟動系統服務。你可以在ZygoteInit類的」startSystemServer」方法中找到源代碼。
核心服務:
啟動電源管理器;
創建Activity管理器;
啟動電話注冊;
啟動包管理器;
設置Activity管理服務為系統進程;
啟動上下文管理器;
啟動系統Context Providers;
啟動電池服務;
啟動定時管理器;
啟動感測服務;
啟動窗口管理器;
啟動藍牙服務;
啟動掛載服務。
其他服務:
啟動狀態欄服務;
啟動硬體服務;
啟動網路狀態服務;
啟動網路連接服務;
啟動通知管理器;
啟動設備存儲監視服務;
啟動定位管理器;
啟動搜索服務;
啟動剪切板服務;
啟動登記服務;
啟動壁紙服務;
啟動音頻服務;
啟動耳機監聽;
啟動AdbSettingsObserver(處理adb命令)。
第七步:引導完成
一旦系統服務在內存中跑起來了,Android就完成了引導過程。在這個時候「ACTION_BOOT_COMPLETED」開機啟動廣播就會發出去。
㈣ Android初探開機引導
因為需求有做開機引導,所以簡單的學習下這塊功能的流程,並簡單的做個總結
主要參考文章:
https://www.jianshu.com/p/d2951f6fb2a8
https://blog.csdn.net/ansondroider/article/details/103297638
做開機引導,主要要做到的效果就是 只有第一次使用的時候會打開,只打開一次,當執行完開機引導的流程之後,之後開機都不會再展示
要實現開機引導,那麼就一定是系統應用,按照原理來說,需要兩個步驟,第一,需要引導頁的優先順序比LAUNCHER高。第二,需要流程完畢之後執行某些操作讓應用下次不會啟動。
可以設置android:priority屬性,系統會判斷啟動priority優先順序高的。
這樣配置之後,其它應用的優先順序如果沒有設置的話默認就是0,這樣就會優先打開引導頁。
自己可以在引導頁中寫自己想要做的邏輯。當執行完所有邏輯之後,需要配置
這里主要做了設置Settings.Global.DEVICE_PROVISIONED和Settings.Secure.USER_SETUP_COMPLETE兩個參數,還有PackageManager.setComponentEnabledSetting方法禁用組件
第一個參數是組件名
第二個參數是狀態
不可用狀態:COMPONENT_ENABLED_STATE_DISABLED
可用狀態:COMPONENT_ENABLED_STATE_ENABLED
默認狀態:COMPONENT_ENABLED_STATE_DEFAULT
第三個參數flags
DONT_KILL_APP或者0,0表示殺死包含該組件的app
運行時會發現設置priority優先順序比LAUNCHER高,在開機之後也會提示讓你選擇打開應用,而不是默認打開優先順序高的,關於這個問題,可以參考這篇文章
https://blog.csdn.net/ansondroider/article/details/103297638
只需要把應用安裝到system/priv-app中,就能解決這個問題。正常來說一般系統應用也是安裝在這么文件夾中,只是平時調試的時候會為了方便直接run,所以可能出現這個問題。
將應用安裝到該文件夾中可以使用這個命令,然後重啟
看了很多文章,都沒有講到為什麼要設置這兩屬性,因為要達成目的,我們只需要設置priority和調用setComponentEnabledSetting方法就行,為什麼要設置這兩個參數?不設置會有什麼影響。
其實簡單來說,系統在其他地方有用到這兩個參數,舉個簡單的例子,我直接
去運行程序,能夠很明顯的測出這種情況下按Home鍵沒反應,除此之外屏保也會不顯示。
所以這兩個參數還是需要在這個地方設為1的。
㈤ Android系統啟動之init.rc文件解析過程
第一篇: Android系統啟動之bootloader
第二篇: Android系統啟動之Init流程(上)
第三篇: Android系統啟動之Init流程(下)
第四篇: Android系統啟動之init.rc文件解析過程
第五篇: Android系統啟動之zyogte進程
第六篇: Android系判嘩統啟動之zyogte進程java(上)
第七篇: Android系統啟動之zyogte進程java(下)
第八篇: Android系統啟動之SystemServer
Android init.rc文件由系統第一個啟動的init程序解析。是啟動系統服務使用的文件。
主要包含了四種類型的語句:
Action和services顯式聲明了一個語句塊,而commands和options屬於最近聲明的語句塊。
在第一個語句塊之前 的commands和options會被忽略.
基本規則如下:
動掘螞行作表示了一組命令(commands)組成.動作包括一個觸發器,決定了何時運行這個動作。
注意: 當觸發器的條件滿足時,這個動作會被增加到已被運行的隊列尾。假設此動作在隊列中已經存在,那麼它將不會運行.
一個動作所包括的命令將被依次運行。
在"動作"(action)裡面的,on後面物隱跟著的字元串是觸發器(trigger),trigger是一個用於匹配某種事件類型的字元串,它將對應的Action的執行。
觸發器(trigger)有幾種格式:
常見的格式:
command是action的命令列表中的命令,或者是service中的選項 onrestart 的參數命令.
命令將在所屬事件發生時被一個個地執行.
常見命令:
服務是指那些須要在系統初始化時就啟動或退出時自己主動重新啟動的程序.
解釋一下各個參數:
options是Service的修訂項。它們決定一個服務何時以及如何運行.
使用例子:
源碼路徑 system/core/init/init.cpp 中:
開始解析rc文件.
ParseConfig函數在文件 core/init/init_parser.cpp 140行:
ParseConfigFile函數:
Android init.rc文件淺析
安卓系統啟動--3init.rc解析
init.rc深入學習
㈥ Android中的Activity詳解--啟動模式與任務棧
目錄
activity的簡單介紹就不寫了,作為最常用的四大組件之一,肯定都很熟悉其基本用法了。
首先,是都很熟悉的一張圖,即官方介紹的Activity生命周期圖.
情景:打開某個應用的的FirstActivity調用方法如下:
由於之前已經很熟悉了,這里就簡單貼一些圖。
按下返回鍵:
重新打開並按下home鍵:
再重新打開:
在其中打開一個DialogActivity(SecondActivity)
按下返回:
修改SecondAcitvity為普通Activity,依舊是上述操作:
這里強調一下 onSaveInstanceState(Bundle outState) 方法的調用時機:
當Activity有可能被系統殺掉時調用,注意,一定是被系統殺掉,自己調用finish是不行的。
測試如下:FirstActivity啟動SecondActivity:
一個App會包含很多個Activity,多個Activity之間通過intent進行跳轉,那麼原始的Activity就是使用棧這個數據結構來保存的。
Task
A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (the back stack ), in the order in which each activity is opened.
即若干個Activity的集合的棧表示一個Task。
當App啟動時如果不存在當前App的任務棧就會自動創建一個,默認情況下一個App中的所有Activity都是放在一個Task中的,但是如果指定了特殊的啟動模式,那麼就會出現同一個App的Activity出現在不同的任務棧中的情況,即會有任務棧中包含來自於不同App的Activity。
標准模式,在不指定啟動模式的情況下都是以此種方式啟動的。每次啟動都會創建一個新的Activity實例,覆蓋在原有的Activity上,原有的Activity入棧。
測試如下:在FirstActivity中啟動FirstActivity:
當只有一個FirstActivity時堆棧情況:
此種模式下,Activity在啟動時會進行判斷,如果當前的App的棧頂的Activity即正在活動的Activity就是將要啟動的Activity,那麼就不會創建新的實例,直接使用棧頂的實例。
測試,設置FirstActivity為此啟動模式,多次點擊FirstActivity中的啟動FirstActivity的按鈕查看堆棧情況:
(其實點擊按鈕沒有啟動新Activity的動畫就可以看出並沒有啟動新Activity)
大意就是:
對於使用singleTop啟動或Intent.FLAG_ACTIVITY_SINGLE_TOP啟動的Activity,當該Activity被重復啟動(注意一定是re-launched,第一次啟動時不會調用)時就會調用此方法。
且調用此方法之前會先暫停Activity也就是先調用onPause方法。
而且,即使是在新的調用產生後此方法被調用,但是通過getIntent方法獲取到的依舊是以前的Intent,可以通過setIntent方法設置新的Intent。
方法參數就是新傳遞的Intent.
1.如果是同一個App中啟動某個設置了此模式的Activity的話,如果棧中已經存在該Activity的實例,那麼就會將該Activity上面的Activity清空,並將此實例放在棧頂。
測試:SecondActivity啟動模式設為singleTask,啟動三個Activity:
這個模式就很好記,以此模式啟動的Activity會存放在一個單獨的任務棧中,且只會有一個實例。
測試:SecondActivity啟動模式設為singleInstance
結果:
顯然,啟動了兩次ThirdActivity任務棧中就有兩個實例,而SecondActivity在另外一個任務棧中,且只有一個。
在使用Intent啟動一個Activity時可以設置啟動該Activity的啟動模式:
這個屬性有很多,大致列出幾個:
每個啟動的Activity都在一個新的任務棧中
singleTop
singleTask
用此種方式啟動的Activity,在它啟動了其他Activity後,會自動finish.
官方文檔介紹如下:
這樣看來的話,通俗易懂的講,就是給每一個任務棧起個名,給每個Activity也起個名,在Activity以singleTask模式啟動時,就檢查有沒有跟此Activity的名相同的任務棧,有的話就將其加入其中。沒有的話就按照這個Activity的名創建一個任務棧。
測試:在App1中設置SecondActivity的taskAffinity為「gsq.test」,App2中的ActivityX的taskAffinity也設為「gsq.test」
任務棧信息如下:
結果很顯然了。
測試:在上述基礎上,在ActivityX中進行跳轉到ActivityY,ActivityY不指定啟動模式和taskAffinity。結果如下:
這樣就沒問題了,ActivityY在一個新的任務棧中,名稱為包名。
這時從ActivityY跳轉到SecondActivity,那應該是gsq.test任務棧只有SecondActivity,ActivityX已經沒有了。因為其啟動模式是singleTask,在啟動它時發現已經有一個實例存在,就把它所在的任務棧上面的Activity都清空了並將其置於棧頂。
還有一點需要提一下,在上面,FirstActivity是App1的lunch Activity,但是由於SecondActivity並沒有指定MAIN和LAUNCHER過濾器,故在FirstActivity跳轉到SecondActivity時,按下home鍵,再點開App1,回到的是FirstActivity。
大致就先寫這么多吧,好像有點長,廢話有點多,估計也有錯別字,不要太在意~~~
㈦ 安卓應用啟動詳解:從Zygote到你的Activity.onCreate()
翻譯自: https://android.jlelse.eu/android-application-launch-explained-from-zygote-to-your-activity-oncreate-8a8f036864b
這篇文章講解當用戶點擊應用圖標時,安卓如何啟動你的應用。安卓系統做了很多幕後工作,來使得你的launch activity對用戶可見。本文通過重要階段的講解和調用序列詳細講解這一過程。
安卓應用在這兩個方面是獨特的:
多個入口點 :Android應用程序由不同的組件組成,它們可以調用其他應用程序擁有的組件。這些組件大致對應於任何應用程序的多個入口點。因此,它們不同於具有像main()方法那樣的單個入口點的傳統應用程序。
擁有自己的小世界 :每個Android應用程序都生活在自己的世界中,它在單獨的進程中運行,擁有自己的Dalvik VM實例,並分配有唯一的用戶ID。
必要時會啟動Android進程。
每當用戶或其他系統組件請求執行屬於您應用程序的組件(可能是服務,活動或意圖接收器)時,Android系統都會為您的應用程序啟動一個新進程(如果尚未運行)。通常,進程一直運行直到被系統殺死。應用程序流程是按需創建的,在您看到應用程序的啟動活動啟動並運行之前,發生了許多事情。
每個應用程序都在其自己的進程中運行 :默認情況下,每個Android應用程序都在其自己的Android進程中運行,而這個進程只不過是一個Linux進程,而該進程首先需要一個執行線程。例如,當您單擊電子郵件中的超鏈接時,網頁將在瀏覽器窗口中打開。您的郵件客戶端和瀏覽器是兩個單獨的應用程序,它們分別在兩個單獨的進程中運行。click事件使Android平台啟動新進程,以便它可以在其自身進程的上下文中實例化瀏覽器活動。這對於應用程序中的任何其他組件同樣適用。
讓我們退後一會兒,快速瀏覽一下系統啟動過程。與大多數基於Linux的系統一樣,啟動載入程序在啟動時將載入內核並啟動init進程。然後,init會生成稱為「守護程序」的低級Linux進程,例如android debug守護程序,USB守護程序等。這些守護程序通常處理低級硬體介面,包括無線電介面。
然後,初始化過程會啟動一個非常有趣的過程,稱為「zygote'。
顧名思義,這是其餘Android應用程序的開始。這是初始化Dalvik虛擬機的第一個實例的過程。它還預載入Android應用程序框架和系統上安裝的各種應用程序使用的所有常見類。因此,它准備進行復制。它統計偵聽套接字介面上的將來請求,以產生新的虛擬機(VM)來管理新的應用程序進程。收到新請求後,它會分叉以創建一個新進程,該進程將獲取預先初始化的VM實例。
zygote之後,init啟動運行時過程。
然後zygote分叉以啟動一個名為System server的託管良好的進程。系統伺服器在其自己的上下文中啟動所有核心平台服務,例如活動管理器服務和硬體服務。
此時,完整的堆棧已准備就緒,可以啟動第一個應用程序流程-主頁應用程序,該應用程序顯示主屏幕(也稱為啟動器應用程序)。
click事件被轉換為 startActivity(intent), 並通過Binder IPC路由到 ActivityManagerService 。ActvityManagerService執行多個步驟
如您所見,當用戶單擊圖標並啟動新應用程序時,許多事情發生在幕後。這是全圖:
流程創建:
ActivityManagerService 通過調用 startProcessLocked() 方法創建一個新進程,該方法通過套接字連接將參數發送到Zygote進程。Zygote派生自己並調用 ZygoteInit.main() ,然後實例化 ActivityThread 對象並返回新創建的進程的進程ID。
默認情況下,每個進程都有一個線程。主線程有一個 Looper 實例來處理來自消息隊列的消息,並且它在 run() 方法的每次迭代中都調用 Looper.loop() 。 Looper 的工作是從消息隊列中彈出消息並調用相應的方法來處理它們。然後,ActivityThread通過隨後調用 Looper.prepareLoop() 和 Looper.loop()來 啟動消息循環。
以下序列詳細捕獲了調用序列:
<figcaption class="jv jw di dg dh jx jy bo b fc cp ga" data-selectable-paragraph="" style="box-sizing: inherit; font-weight: 400; font-family: sohne, "Helvetica Neue", Helvetica, Arial, sans-serif; line-height: 20px; margin-left: auto; margin-right: auto; max-width: 728px; font-size: 14px; color: rgb(117, 117, 117); margin-top: 10px; text-align: center;">Android應用啟動:單擊事件以執行Looper調用順序</figcaption>
應用程序綁定:
下一步是將此新創建的過程附加到特定應用程序。這是通過在線程對象上調用 bindApplication() 來完成的。此方法將 BIND_APPLICATION 消息發送到消息隊列。該消息由 Handler 對象檢索,該對象隨後調用 handleMessage() 方法以觸發特定於消息的操作 -handleBindApplication() 。此方法調用 makeApplication() 方法,該方法將應用程序特定的類載入到內存中。
下圖描述了該調用序列。
<figcaption class="jv jw di dg dh jx jy bo b fc cp ga" data-selectable-paragraph="" style="box-sizing: inherit; font-weight: 400; font-family: sohne, "Helvetica Neue", Helvetica, Arial, sans-serif; line-height: 20px; margin-left: auto; margin-right: auto; max-width: 728px; font-size: 14px; color: rgb(117, 117, 117); margin-top: 10px; text-align: center;">Android應用啟動:BIND_APPLICATION消息處理</figcaption>
啟動活動:
在上一步之後,系統包含負責應用程序的進程,並將應用程序類載入到進程的私有內存中。在新創建的流程和現有流程之間,啟動活動的調用順序很常見。
實際的啟動過程從 realStartActivity() 方法開始, 該 方法在應用程序線程對象上調用 sheleLaunchActivity() 。此方法將 LAUNCH_ACTIVITY 消息發送到消息隊列。該消息由 handleLaunchActivity() 方法處理,如下所示。
假設用戶單擊「視頻瀏覽器」應用程序。啟動該活動的調用順序如圖所示。
<figcaption class="jv jw di dg dh jx jy bo b fc cp ga" data-selectable-paragraph="" style="box-sizing: inherit; font-weight: 400; font-family: sohne, "Helvetica Neue", Helvetica, Arial, sans-serif; line-height: 20px; margin-left: auto; margin-right: auto; max-width: 728px; font-size: 14px; color: rgb(117, 117, 117); margin-top: 10px; text-align: center;">Android應用啟動: LAUNCH_ACTIVITY消息處理 </figcaption>
該活動通過 onCreate() 方法調用開始其託管生命周期。該活動通過 onRestart() 調用進入前台,並通過 onStart() 調用開始與用戶進行交互。
㈧ android 怎麼設置activity的啟動模式
android 怎麼獲取一個activity啟動模式
在Android中每個界面都是一個Activity,切換界面操作其實是多個不同Activity之間的實例化操作。在Android中Activity的啟動模式決定了Activity的啟動運行方式。
Android總Activity的啟動模式分為四種:
Activity啟動模式設置:
<activity android:name=".MainActivity" android:launchMode="standard" />
Activity的四種啟動模式:
1. standard
模式啟動模式,每次激活Activity時都會創建Activity,並放入任務棧中。
2. singleTop
如果在任務的棧頂正好存在該Activity的實例, 就重用該實例,否者就會創建新的實例並放入棧頂(即使棧中已經存在該Activity實例,只要不在棧頂,都會創建實例)。
3. singleTask
如果在棧中已經有該Activity的實例,就重用該實例(會調用實例的onNewIntent())。重用時,會讓該實例回到棧頂,因此在它上面的實例將會被移除棧。如果棧中不存在該實例,將會創建新的實例放入棧中。
4. singleInstance
在一個新棧中創建該Activity實例,並讓多個應用共享改棧中的該Activity實例。一旦改模式的Activity的實例存在於某個棧中,任何應用再激活改Activity時都會重用該棧中的實例,其效果相當於多個應用程序共享一個應用,不管誰激活該Activity都會進入同一個應用中。
其中standard是系統默認的啟動模式。
下面通過實例來演示standard的運行機制:
1 private TextView text_show;
2 private Button btn_mode;
3
4 @Override
5 public void onCreate(Bundle savedInstanceState) {
6 super.onCreate(savedInstanceState);
7 setContentView(R.layout.activity_main);
8
9 text_show = (TextView) this.findViewById(R.id.text_show);
10
11 text_show.setText(this.toString());
12
13 btn_mode = (Button) this.findViewById(R.id.btn_mode);
14
15 }
16
按鈕單擊事件
17 public void LaunchStandard(View v){
18 startActivity(new Intent(this,MainActivity.class));
19
20 text_show.setText(this.toString());
21 }
如何設置Activity的啟動模式
- Activity的四種啟動模式:standard:這是默認模式,每次激活Activity時都會創建Activity實例,並放入任務棧中。 singleTop: 如果在任務的棧頂正好存在該Activity的實例,就重用該實例( 會調用實例的 onNewIntent() ),否則就會創建新的實例並放...
android 主activity用什麼啟動模式
在android里,有4種activity的啟動模式,分別為:
「standard」 (默認)
「singleTop」
「singleTask」
「singleInstance」
1. 如何決定所屬task
「standard」和」singleTop」的activity的目標task,和收到的Intent的發送者在同一個task內,除非intent包括參數FLAG_ACTIVITY_NEW_TASK。
如果提供了FLAG_ACTIVITY_NEW_TASK參數,會啟動到別的task里。
2. 是否允許多個實例
「standard」和」singleTop」可以被實例化多次,並且存在於不同的task中,且一個task可以包括一個activity的多個實例;
「singleTask」和」singleInstance」則限制只生成一個實例,並且是task的根元素。
singleTop要求如果創建intent的時候棧頂已經有要創建 的Activity的實例,則將intent發送給該實例,而不發送給新的實例。
3. 是否允許其它activity存在於本task內
「singleInstance」獨佔一個task,其它activity不能存在那個task里;如果它啟動了一個新的activity,不管新的activity的launch mode 如何,新的activity都將會到別的task里運行(如同加了FLAG_ACTIVITY_NEW_TASK參數)。
而另外三種模式,則可以和其它activity共存。
4. 是否每次都生成新實例
「standard」對於沒一個啟動Intent都會生成一個activity的新實例;
「singleTop」的activity如果在task的棧頂的話,則不生成新的該activity的實例,直接使用棧頂的實例,否則,生成該activity的實例。
比如現在task棧元素為A-B-C-D(D在棧頂),這時候給D發一個啟動intent,如果D是 「standard」的,則生成D的一個新實例,棧變為A-B-C-D-D。
如果D是singleTop的話,則不會生產D的新實例,棧狀態仍為A-B-C-D
如果這時候給B發Intent的話,不管B的launchmode是」standard」 還是 「singleTop」 ,都會生成B的新實例,棧狀態變為A-B-C-D-B。
「singleInstance」是其所在棧的唯一activity,它會每次都被重用。
「singleTask」如果在棧頂,則接受intent,否則,該intent會被丟棄,但是該task仍會回到前台。
當已經存在的activity實例處理新的intent時候,會調用onNewIntent()方法
如果收到intent生成一個activity實例,那麼用戶可以通過back鍵回到上一個狀態;如果是已經存在的一個activity來處理這個intent的話,用戶不能通過按back鍵返回到這之前的狀態。
總結如下:
standard 每次都會新建,每個Task都可以有,且每個Task都可以有多個實例(每個Task都可以有,且可以有多個)
singleTop 當前實例如果在棧頂,就不新建實例,調用其OnNewIntent。 如不在棧頂,則新建實例 (每個Task都可以有,且可以有多個,在棧頂時可復用)
singleTask 新建一個Task,如果已經有其他的Task並且包含該實例,那就直接調用那個Task的實例。(只有一個Task中會有)
singleInstance 新建一個Task,且在該Task中只有它的唯一一個實例。 (只有一個Task會有,且該Task中只有它)
FLAG_ACTIVITY_NEW_TASK 類似singleTask
FLAG_ACTIVITY_SINGLE_TOP 類似singleTop
FLAG_ACTIVITY_CLEAR_TOP 無對應
Android開發,activity的默認啟動模式為標准啟動模式,什麼時候會用到其他的啟動模式?
啟動模式簡單地說就是Activity啟動時的策略,在AndroidManifest.xml中的標簽的android:launchMode屬性設置;
啟動模式有4種,分別為standard、singleTop、singleTask、singleInstance;
講解啟動模式之前,有必要先了解一下「任務棧」的概念;
一 :
standard 模式:這個就沒有什麼好說的了,Android默認Activity啟動的模式 就是 standard,如果有3個 Activity,Act1,Act2,Act3, 如果從Act1 啟動到Act2 ,在啟動到Act3,那麼Android 的任務棧(task stack)分別為 Act1、Act2、Act3,Act3 在棧頂,如果此時按手機返回鍵,則需要返回3次才能返回到桌面(假設是從桌面啟動的demo),任務棧分銷毀掉 Act3,Act2,最後Act1 。
二 :singleTop模式:
實驗效果:
singleTop模式:該啟動模式和standard模式相差不多,任務棧分配也很相似,如:現有 act1,act 2,在act2 清單文件中配置 android:launchMode="singleTop" ,其他都是默認standard 模式, 若從桌面啟動該實驗demo,從act 1,到act2 ,那麼任務棧則分配為,act1,act2,此時該任務棧和 standard 模式任務棧分配則完全相同,接下來則說明不同的地方,如果在act2 界面中 啟動 到act1, 此時的 任務棧 情況則為 act1,act2,act1,在由act1 啟動到act2,在啟動到act2,進行多次啟動,(在act2界面)任務棧的情況則為,act1,act2,act1,act2,棧頂的act2 則不會重新創建,則會復用act2 該 Activit, 依次類推。
理論知識:
singleTop,如果任務棧的棧頂元素是要被激活的組件,不會創建新的Activity放在任務棧,而是會復用棧頂的Activity。 如果發現棧頂的元素不是要激活的Activity,就會創建新的Activity 放置到任務棧裡面
singleTop模式應用場景 :
App程序中(或瀏覽器中)保存的書簽,假如用戶看到一個界面保存自己喜歡的標簽,假如要保存10個,這個時候用戶在返回鍵的時候,則會返回10次才能返回到App應用中, Android下singleTop 則解決該問題。
三singleTask 模式 :
實驗效果 相差不大,實驗內容就不多說了,自己可以寫個小demo,兩個Activity,每個Activiy 有兩個button,可以相互啟動 打日誌去動手查看,會理解更加深刻,可以參照著 SingleTop模式去實驗,以下只是講解下 和SingleTop的區別:
區別如下:(理論知識)
SingleTask 操作模式,一般和singleTop操作模式類似,如果他發現任務棧裡面已經有了要啟動的這個Activity,他會清空這個Activity所在的任務棧上面的所有Activiy,然後直接復用這個已經存在的Activity 。
應用場景:
如果一個App中,有一個功能需要載入網頁內容 ,打開一個 browserActiviy現在網頁內容,則內存開銷非常大,首先要初始化webkit /c++ 嵌入式瀏覽器內核broweractivity 配置了singleTask,空間換時間,使用該模式可以節省內存開銷。
四 :singleinstance 模式 :
直接理論知識吧」:
singleInstance操作模式會新開啟一個任務棧,跟其他普通Activity不是 同一個任務棧,比較牛,他的模式流程是 首先要新開啟一個新的任務棧把要激活的Activity放置到新的 任務棧里,這個任務棧裡面只有且 只有一個實例,也比較極端吧。說比較極端也跟他的應用場景有關系。
應用場景 :
App各種詞典,向有道詞典,什麼金山詞典,說極端是因為不想被放置到同一個任務棧裡面,它是全局的系統程序應用,達到節省內存的使用目的。
win7 系統 怎麼設置uefi啟動模式
存有ghost版win7系統iso鏡像文件的u啟動uefi u盤啟動盤插在電腦u *** 介面上,然後重啟電腦,在出現開機畫面時用一鍵u盤啟動快捷鍵的方法進入到啟動項選擇窗口,然後將游標移至UEFI:開頭的項(注意:一定要選擇該項),按回車鍵執行等待進入到u啟動win pe系統,u啟動裝機工具會自動開啟,並載入到u啟動uefi u盤啟動盤中准備的win7系統安裝程序,點擊選擇c盤為系統安裝盤,再點擊「確定」按鈕繼續
隨即會彈出一個詢問是否執行該操作的提示窗口,點擊「確定」按鈕執行操作
然後耐心等待win7系統釋放完成並自動重啟電腦即可
電腦重啟後會完成系統後續程序安裝應用,直到進入win7系統桌面即可
android開發 activity啟動模式中singleTop的疑問
樓主的這一段理論似乎有點不太准確 「在D完成操作以後,我啟動了系統內置的瀏覽器E,根據sdk的說法,瀏覽器E被放進了一個新任務。那麼現在有兩個任務」 你憑什麼確定瀏覽器E被放進了一個新的Task呢? 在啟動瀏覽器E的Intent里設置了flag? intentandroid開發 activity啟動模式中singleTop的疑問
android-Android activity 的啟動模式.新人提問,大俠在哪
Activity的四種啟動模式:standard:這是默認模式,每次激活Activity時都會創建Activity實例,並放入任務棧中。
singleTop: 如果在任務的棧頂正好存在該Activity的實例,就重用該實例( 會調用實例的 onNewIntent() ),否則就會創建新的實例並放入棧頂,即使棧中已經存在該Activity的實例,只要不在棧頂,都會創建新的實例。
singleTask:如果在棧中已經有該Activity的實例,就重用該實例(會調用實例的 onNewIntent() )。重用時,會讓該實例回到棧頂,因此在它上面的實例將會被移出棧。如果棧中不存在該實例,將會創建新的實例放入棧中。
singleInstance:在一個新棧中創建該Activity的實例,並讓多個應用共享該棧中的該Activity實例。一旦該模式的Activity實例已經存在於某個棧中,任何應用再激活該Activity時都會重用該棧中的實例( 會調用實例的 onNewIntent() )。其效果相當於多個應用共享一個應用,不管誰激活該 Activity 都會進入同一個應用中。
位置在 AndroidManifest.xml 文件中 Activity 元素的 android:launchMode 屬性。
不知道你要問什麼,為你解答
activity的啟動模式有哪些
Activity的四種啟動模式:standard:這是默認模式,每次激活Activity時都會創建Activity實例,並放入任務棧中。
singleTop: 如果在任務的棧頂正好存在該Activity的實例,就重用該實例( 會調用實例的 onNewIntent() ),否則就會創建新的實例並放入棧頂,即使棧中已經存在該Activity的實例,只要不在棧頂,都會創建新的實例。
singleTask:如果在棧中已經有該Activity的實例,就重用該實例(會調用實例的 onNewIntent() )。重用時,會讓該實例回到棧頂,因此在它上面的實例將會被移出棧。如果棧中不存在該實例,將會創建新的實例放入棧中。
singleInstance:在一個新棧中創建該Activity的實例,並讓多個應用共享該棧中的該Activity實例。一旦該模式的Activity實例已經存在於某個棧中,任何應用再激活該Activity時都會重用該棧中的實例( 會調用實例的 onNewIntent() )。其效果相當於多個應用共享一個應用,不管誰激活該 Activity 都會進入同一個應用中。
位置在 AndroidManifest.xml 文件中 Activity 元素的 android:launchMode 屬性。
㈨ Android啟動廣播時怎樣往廣播中傳遞參數
在android中使用廣播來讓其他監聽廣播的地方能夠對相應的事情做處理,但有的時候需要傳遞一些其他的附帶值,而這個時候是可以直接用播放廣播的intent來傳遞的。x0dx0a例:x0dx0aIntent intent = new Intent();x0dx0aintent.putExtra("msgPersons", msgPersons);x0dx0aintent.setAction(Constant.hasMsgUpdatedAction);x0dx0aintent.putExtra("userId", userId);x0dx0aintent.putExtra("msgCount", messages.size());x0dx0asendBroadcast(intent);
㈩ 在開發android程序時,如何在一個project里選擇啟動不同的activity類怎麼設置啟動參數
首先我不清楚你的仿山要求。
按我的理解:
1.你不要求啟動ac1.java,而是選擇啟動ac2.java。如果這樣,你可以在AndroidManifest.xml中更改啟動類,假如ac2.java的類名是TwoActivity,
將(類名..)改為TwoActivity。
<activity
android:name=".(類名..)"
android:label="@string/app_name"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
2.你既要啟動ac1.java,也要啟動ac2.java,我認為備帆中不能同時啟動,畢竟你就一個屏幕,不可能顯示兩個屏幕的內容。除非你有一個選擇,遇到第一種情況顯示ac1.java;遇到第二種情況顯示ac2.java。但是其中存在一個問題,這個if語句在那裡寫,xml中似乎沒辦法寫,也就只能在java文件裡面寫了。也就是說ac1.java與ac2.java的代碼要組合起來,寫在一個.java文件中。
你可以從新建立一個Activity,你有兩個布局XML文件one.xml與two.xml,在這個Activity中的onCreate方法中
if (情況1){
setContentView(R.layout.one);
} else (情況2) {
setContentView(R.layout.two);
}
這樣你就可以選擇兩種布局,情況1的時候初始化情況1的變數,情況2的時候轎州初始化情況2的變數,分開寫就可以了。
3.就是分順序啟動2個文件,從ac1.java中跳轉到ac2.java中,在ac1.java中使用startActivity(intent);就可以跳轉。