翻譯自:
創(chuàng)新互聯(lián)公司成立與2013年,先為孫吳等服務建站,孫吳等地企業(yè),進行企業(yè)商務咨詢服務。為孫吳企業(yè)網站制作PC+手機+微官網三網同步一站式服務解決您的所有建站問題。
這篇文章講解當用戶點擊應用圖標時,安卓如何啟動你的應用。安卓系統(tǒng)做了很多幕后工作,來使得你的launch activity對用戶可見。本文通過重要階段的講解和調用序列詳細講解這一過程。
安卓應用在這兩個方面是獨特的:
多個入口點 :Android應用程序由不同的組件組成,它們可以調用其他應用程序擁有的組件。這些組件大致對應于任何應用程序的多個入口點。因此,它們不同于具有像main()方法那樣的單個入口點的傳統(tǒng)應用程序。
擁有自己的小世界 :每個Android應用程序都生活在自己的世界中,它在單獨的進程中運行,擁有自己的Dalvik VM實例,并分配有唯一的用戶ID。
必要時會啟動Android進程。
每當用戶或其他系統(tǒng)組件請求執(zhí)行屬于您應用程序的組件(可能是服務,活動或意圖接收器)時,Android系統(tǒng)都會為您的應用程序啟動一個新進程(如果尚未運行)。通常,進程一直運行直到被系統(tǒng)殺死。應用程序流程是按需創(chuàng)建的,在您看到應用程序的啟動活動啟動并運行之前,發(fā)生了許多事情。
每個應用程序都在其自己的進程中運行 :默認情況下,每個Android應用程序都在其自己的Android進程中運行,而這個進程只不過是一個Linux進程,而該進程首先需要一個執(zhí)行線程。例如,當您單擊電子郵件中的超鏈接時,網頁將在瀏覽器窗口中打開。您的郵件客戶端和瀏覽器是兩個單獨的應用程序,它們分別在兩個單獨的進程中運行。click事件使Android平臺啟動新進程,以便它可以在其自身進程的上下文中實例化瀏覽器活動。這對于應用程序中的任何其他組件同樣適用。
讓我們退后一會兒,快速瀏覽一下系統(tǒng)啟動過程。與大多數基于Linux的系統(tǒng)一樣,啟動加載程序在啟動時將加載內核并啟動init進程。然后,init會生成稱為“守護程序”的低級Linux進程,例如android debug守護程序,USB守護程序等。這些守護程序通常處理低級硬件接口,包括無線電接口。
然后,初始化過程會啟動一個非常有趣的過程,稱為“zygote'。
顧名思義,這是其余Android應用程序的開始。這是初始化Dalvik虛擬機的第一個實例的過程。它還預加載Android應用程序框架和系統(tǒng)上安裝的各種應用程序使用的所有常見類。因此,它準備進行復制。它統(tǒng)計偵聽套接字接口上的將來請求,以產生新的虛擬機(VM)來管理新的應用程序進程。收到新請求后,它會分叉以創(chuàng)建一個新進程,該進程將獲取預先初始化的VM實例。
zygote之后,init啟動運行時過程。
然后zygote分叉以啟動一個名為System server的托管良好的進程。系統(tǒng)服務器在其自己的上下文中啟動所有核心平臺服務,例如活動管理器服務和硬件服務。
此時,完整的堆棧已準備就緒,可以啟動第一個應用程序流程-主頁應用程序,該應用程序顯示主屏幕(也稱為啟動器應用程序)。
click事件被轉換為 startActivity(intent), 并通過Binder IPC路由到 ActivityManagerService 。ActvityManagerService執(zhí)行多個步驟
如您所見,當用戶單擊圖標并啟動新應用程序時,許多事情發(fā)生在幕后。這是全圖:
流程創(chuàng)建:
ActivityManagerService 通過調用 startProcessLocked() 方法創(chuàng)建一個新進程,該方法通過套接字連接將參數發(fā)送到Zygote進程。Zygote派生自己并調用 ZygoteInit.main() ,然后實例化 ActivityThread 對象并返回新創(chuàng)建的進程的進程ID。
默認情況下,每個進程都有一個線程。主線程有一個 Looper 實例來處理來自消息隊列的消息,并且它在 run() 方法的每次迭代中都調用 Looper.loop() 。 Looper 的工作是從消息隊列中彈出消息并調用相應的方法來處理它們。然后,ActivityThread通過隨后調用 Looper.prepareLoop() 和 Looper.loop()來 啟動消息循環(huán)。
以下序列詳細捕獲了調用序列:
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應用啟動:單擊事件以執(zhí)行Looper調用順序/figcaption
應用程序綁定:
下一步是將此新創(chuàng)建的過程附加到特定應用程序。這是通過在線程對象上調用 bindApplication() 來完成的。此方法將 BIND_APPLICATION 消息發(fā)送到消息隊列。該消息由 Handler 對象檢索,該對象隨后調用 handleMessage() 方法以觸發(fā)特定于消息的操作 -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
啟動活動:
在上一步之后,系統(tǒng)包含負責應用程序的進程,并將應用程序類加載到進程的私有內存中。在新創(chuàng)建的流程和現有流程之間,啟動活動的調用順序很常見。
實際的啟動過程從 realStartActivity() 方法開始, 該 方法在應用程序線程對象上調用 sheduleLaunchActivity() 。此方法將 LAUNCH_ACTIVITY 消息發(fā)送到消息隊列。該消息由 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程序強行關閉后,讓程序自動啟動的方法為:
1、自己建一個service,不斷的去判斷,如果Activity掛掉了,就在service里啟動它。
2、在程序里面寫個廣播什么的到程序里面 ,比如 一些apk程序。一檢測到wifi開啟,廣播就激發(fā),啟動程序。
AMS主要功能:
AMS是Android中最核心的服務,主要負責系統(tǒng)中四大組件的啟動、切換、調度及應用進程的管理和調度等工作。還負責啟動或殺死應用程序的進程。
WMS主要功能:
為所有窗口分配Surface。
管理Surface的顯示順序、尺寸、位置。
管理窗口動畫。
輸入系統(tǒng)相關:WMS是派發(fā)系統(tǒng)按鍵和觸摸消息的最佳人選,當接收到一個觸摸事件,它需要尋找一個最合適的窗口來處理消息。
PWS主要功能:
PMS 用來管理跟蹤所有應用APK,包括安裝,卸載,解析,控制權限等。
SystemServer也是一個進程,包括AMS、PMS、WMS等等。
zygote意為“受精卵“。Android是基于Linux系統(tǒng)的,而在Linux中,所有的進程都是由init進程直接或者是間接fork出來的,zygote進程也不例外。
App進程是用戶點擊桌面icon時,通過Launcher進程請求SystemServer,再調用Zygote孵化的。
①點擊啟動一個App,Launcher進程采用Binder IPC向ActivityManagerService發(fā)起startActivity請求;
②ActivityManagerService接收到請求后,向zygote進程發(fā)送創(chuàng)建進程的請求;
③Zygote進程fork出新的子進程,即App進程;
④App進程通過Binder IPC向sytem_server進程發(fā)起綁定Application請求;
⑤system_server進程在收到請求后,進行一系列準備工作后,再通過binder IPC向App進程發(fā)送scheduleLaunchActivity請求;
⑥App進程的binder線程(ApplicationThread)在收到請求后,通過handler向主線程發(fā)送LAUNCH_ACTIVITY消息;
⑦主線程在收到Message后,通過發(fā)射機制創(chuàng)建目標Activity,并回調Activity.onCreate()等方法。
⑧到此,App便正式啟動,開始進入Activity生命周期,執(zhí)行完onCreate/onStart/onResume方法,UI渲染結束后便可以看到App的主界面。
備注:
Launcher,PMS,Zygote,App進程是三個獨立的進程,相互通信就需要使用進程間通信機制。與Zygote通信是使用的socket通信,Launcher,PMS,App進程間使用的是Binder機制。
Android adb.exe程序啟動詳細處理步驟如下:
1、打開Android adb.exe程序,輸入:? ? ?netstat -aon|findstr "5037"? 回車;
2、5037 這是adb要的端口,有時候會被其他進程(程序)占用了(一般是會連接手機的軟件)所以要查詢是誰占用了,然后就可以Kill(停止)它;
3、根據上圖然后輸入? ? ?taskkill /pid 1156 /f? ? ?(1156就是占用此端口的進程id);正常情況下,就可以使用adb了,如果還是沒有成功的,可以看看是不是adb.exe被電腦防火墻屏蔽了。
擴展資料:
1、Android adb.exe程序處理方法詳細講解:
cmd命令進入sdk/platform-tools文件下,adb kill-server;
啟動adb服務,adb start-server;
如果啟動失敗,可能是某個進程占用了adb的5037端口,查找占用端口號5037的連接netstat -ano findstr "5037" ;
2、手動結束此進程,重啟adb服務 adb start-server;
adb kill-server --停止adb服務;
adb start-server --開啟adb服務;
參考資料來源:百度百科-Android系統(tǒng)級深入開發(fā):移植與調試
安裝自啟動:
要做這個功能有一個前提,那就是用戶的機器上已經裝過相應應用,也就是說只有升級APK的時候才可以這么干,因為要執(zhí)行的功能需要程序的配合。
具體步驟如下:
首先要知道程序已經安裝完成,所以需要在程序中注冊一個廣播監(jiān)聽(必須是靜態(tài)的,你懂的)apk安裝完成的action:"android.intent.action.PACKAGE_ADDED",在這個廣播的onReceive方法中監(jiān)聽action,并通過intent.getDataString()方法判斷安裝程序的包名是否屬于自己的包名,如果是做下一步操作;
通過Intent顯式或者隱式的啟動你自己的程序。
建議:
??最好不要這樣干,你要考慮一下用戶的感受,特別是那種自動安裝不需要點確認的時候,正在玩游戲、看視頻、看小說、用微信你自動打開一個應用
開機自啟動
android實現開機自啟動可能是移動操作系統(tǒng)中最簡單的了,只需要監(jiān)聽一個開機啟動的Broadcast(廣播)即可。首先寫一個Receiver(即廣播監(jiān)聽器),繼承BroadcastReceiver。
如下所示:
public class BootReceiver extends BroadcastReceiver {
private PendingIntent mAlarmSender;
@Override
public void onReceive(Context context, Intent intent) {
// 在這里干你想干的事(啟動一個Service,Activity等),本例是啟動一個定時調度程序,每30分鐘啟動一個Service去更新數據
mAlarmSender = PendingIntent.getService(context, 0, new Intent(context,
RefreshDataService.class), 0);
long firstTime = SystemClock.elapsedRealtime();
AlarmManager am = (AlarmManager) context
.getSystemService(Activity.ALARM_SERVICE);
am.cancel(mAlarmSender);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime,
30 * 60 * 1000, mAlarmSender);
}
}
接下來,只需要在應用程序配置文件AndroidManifest.xml中注冊這個Receiver來監(jiān)聽系統(tǒng)啟動事件即可
如下所示:
receiver android:name=".service.BootReceiver"
intent-filter
!-- 系統(tǒng)啟動完成后會調用--
action android:name="android.intent.action.BOOT_COMPLETED"
/action
/intent-filter
/receiver
article class="_2rhmJa"
Android 設備開機自啟動的可以用廣播實現,因為 Android 設備開機時會發(fā)送一條開機廣播 "android.intent.action.BOOT_COMPLETED"。接收后實現啟動就完成了。
接下來是準備工作
如果按照上面的全部步驟后操作后,重啟沒有自動啟動程序,怎么辦呢?是怎么回事呢?
*那么首先請檢查一下你的手機是不是安裝了360等安全助手之類的軟件,如果有,請在軟件的自啟動軟件管理中將app設置為允許
*我的手機沒有安裝這些軟件,但是手機中自帶了安全助手,有的手機系統(tǒng)設置里面自帶了自啟動軟件管理的功能 ,所以在這里將我們的app設置為允許開機啟動),重啟手機,測試是否成功。
然而并沒有成功
接收不到BOOT_COMPLETED廣播可能的原因
(1)、BOOT_COMPLETED對應的action和uses-permission沒有一起添加
(2)、應用安裝到了sd卡內,安裝在sd卡內的應用是收不到BOOT_COMPLETED廣播的
(3)、系統(tǒng)開啟了Fast Boot模式,這種模式下系統(tǒng)啟動并不會發(fā)送BOOT_COMPLETED廣播
(4)、應用程序安裝后重來沒有啟動過,這種情況下應用程序接收不到任何廣播,包括BOOT_COMPLETED、ACTION_PACKAGE_ADDED、CONNECTIVITY_ACTION等等。
Android3.1之后,系統(tǒng)為了加強了安全性控制,應用程序安裝后或是(設置)應用管理中被強制關閉后處于stopped狀態(tài),在這種狀態(tài)下接收不到任何廣播,除非廣播帶有FLAG_INCLUDE_STOPPED_PACKAGES標志,而默認所有系統(tǒng)廣播都是FLAG_EXCLUDE_STOPPED_PACKAGES的,所以就沒法通過系統(tǒng)廣播自啟動了。所以Android3.1之后
(1)、應用程序無法在安裝后自己啟動
(2)、沒有ui的程序必須通過其他應用激活才能啟動,如它的Activity、Service、Content Provider被其他應用調用。
存在一種例外,就是應用程序被adb push you.apk /system/app/下是會自動啟動的,不處于stopped狀態(tài)。
并不太懂 我的APP啟動后 已經收到廣播
第一種方式 我再模擬器上 測試 可以 android 9.0版本
桌面設置也會把你的app當成一個桌面主題,還有一個選項是系統(tǒng)桌面,你需要設置成自己的app
如果找不到桌面設置選項,可以從手機設置–應用程序-查看所有應用程序(包括系統(tǒng)的應用程序),找到桌面程序之類的字眼的應用,清楚其默認設置。