1. android 兩個app之間的activity怎麼跳轉
android中intent實現兩個不同應用Activity跳轉,可以用以下的方法: 開發有時需要在一個應用中啟動另一個應用,比如Launcher載入所有的已安裝的程序的列表,當點擊圖標時可以啟動另一個應用。一般我們知道了另一個應用的包名和MainActivit y的名字之後便可以直接通過如下代碼來啟動: [java] view plain Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); ComponentName cn = new ComponentName(packageName, className); intent.setComponent(cn); startActivity(intent); 但是更多的時候,我們一般都不知道目標應用程序的啟動Activity的類名,而只知道包名,接下來就需要這么做了,我封裝成了一個方法,如下所示: [java] view plain private void (String packagename) { // 通過包名獲取此APP詳細信息,包括Activities、services、versioncode、name等等 PackageInfo packageinfo = null; try { packageinfo = getPackageManager().getPackageInfo(packagename, 0); } catch (NameNotFoundException e) { e.printStackTrace(); } if (packageinfo == null) { return; } // 創建一個類別為CATEGORY_LAUNCHER的該包名的Intent Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null); resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER); resolveIntent.setPackage(packageinfo.packageName); // 通過getPackageManager()的queryIntentActivities方法遍歷 List<ResolveInfo> resolveinfoList = getPackageManager() .queryIntentActivities(resolveIntent, 0); ResolveInfo resolveinfo = resolveinfoList.iterator().next(); if (resolveinfo != null) { // packagename = 參數packname String packageName = resolveinfo.activityInfo.packageName; // 這個就是我們要找的該APP的LAUNCHER的Activity[組織形式:packagename.mainActivityname] String className = resolveinfo.activityInfo.name; // LAUNCHER Intent Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); // 設置ComponentName參數1:packagename參數2:MainActivity路徑 ComponentName cn = new ComponentName(packageName, className); intent.setComponent(cn); startActivity(intent); } }
2. Android手機app啟動的時候第一個Activity必須是MainActivity嗎
不是必須MainActivity,可以是任何Activity.
看AndroidManifest.xml中
紅框中代碼決定誰是啟動Activity.
//決定應用程序最先啟動的Activity
//當有多個啟動設置時候,程序會優先調用最前面的activity作為啟動Activity.
<action android:name="android.intent.action.MAIN" />
//決定應用程序是否顯示在程序列表裡
<category android:name="android.intent.category.LAUNCHER" />
3. 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。
大致就先寫這么多吧,好像有點長,廢話有點多,估計也有錯別字,不要太在意~~~
4. Android之Activity全面解析,有些知識點容易忘記
Activity作為安卓四大組件之一,是最重要也是用得最多的組件,涉及的知識點非常多,有些知識點平時開發很少用到,但在某些場景下需要特別注意,本文詳細整理了Activity涉及的知識點,供開發參考。
針對Activity可以提出很多問題,如:
Activity 的生命周期?
Activity 之間的通信方式?
Activity 各種情況下的生命周期?
橫豎屏切換時 Activity 的生命周期?
前台切換到後台,然後再回到前台時 Activity 的生命周期?
彈出 Dialog 的時候按 Home 鍵時 Activity 的生命周期?
兩個Activity之間跳轉時的生命周期?
下拉狀態欄時 Activity 的生命周期?
Activity 與 Fragment 之間生命周期比較?
Activity 的四種 LaunchMode(啟動模式)的區別?
Activity 狀態保存與恢復?
Activity的轉場動畫有哪些實現方式?
Activity的生命周期中怎麼獲取控制項寬高?
onNewIntent的執行時機?
如何連續退出多個Activity?
如何把Acitivty設置成Dialog樣式 ,android:theme="@android:style/Theme.Dialog"
關於橫豎屏切換的生命周期,對應不同的手機,由於廠商定製的原因,會有不同的效果,如設置了configChanges="orientation」在有些手機會執行各個生命周期,但有些手機卻不會執行。
網上常見的結論如下:
但實際的測試如下:
可以看出,不同廠商的手機切屏生命周期會有差異。
從API 13以上,當設備在橫豎切屏時,「屏幕尺寸」也會發生變化,因此為了杜絕切屏導致頁面銷毀重建,需要加上screenSize,使用設置4,即 android:configChanges="orientation|keyboardHidden|screenSize" .
Activity的四種狀態如下:
在activity處於paused或者stoped狀態下,如果系統內存緊張,可能會被銷毀,當重回該activity時會重建,正常返回和被回收後返回的生命周期如下:
如果是回收後返回,onCreate的參數savedInstanceState不為空。
有哪些場景會觸發onNewIntent回調呢?跟啟動模式有關,首先該Activity實例已經存在,再次啟動才可能觸發。一種情況是啟動模式是singleTask或者singleInstance,無論該activity在棧中哪個位置,都會觸發onNewIntent回調,並且把上面其他acitivity移除,另一種情況是啟動模式是singleTop或者以FLAG_ACTIVITY_SINGLE_TOP啟動,並且該activity實例在棧頂,會觸發onNewIntent,如果不在棧頂是重新創建的,不會觸發。
在實際業務開發中,往往碰到需要連續退出多個activity實例,下面整理了幾種常見方法:
● 發送特定廣播
1、在需要處理連續退出的activity注冊該特定廣播;
2、發起退出的activity發送該特定廣播;
3、接收到該廣播的activity 調用finish結束頁面。
● 遞歸退出
1、用startActivityForResult啟動新的activity;
2、前一個頁面finish時,觸發onActvityResult回調,再根據requestCode和resultCode處理是否finish,達到遞歸退出的效果。
● FLAG_ACTIVITY_CLEAR_TOP
通過intent.setFlag(Intent.FLAG_ACTIVITY_CLEAR_TOP)啟動新activity,如果棧中已經有該實例,則會把該activity之上的所有activity關閉,達到singleTop啟動模式的效果。
● 自定義activity棧
1、自定義activity列表,新打開activity則加入棧中,關閉則移除棧;
2、需要退出多個activity時,則循環從棧中移除activity實例,並調用finish。
在討論Activity啟動模式經常提到任務棧,那到底什麼是任務棧?
任務是一個Activity的集合,它使用棧的方式來管理其中的Activity,這個棧又被稱為返回棧(back stack),棧中Activity的順序就是按照它們被打開的順序依次存放的。返回棧是一個典型的後進先出(last in, first out)的數據結構。下圖通過時間線的方式非常清晰地向我們展示了多個Activity在返回棧當中的狀態變化:
taskAffinity 任務相關性,可以用於指定一個Activity更加願意依附於哪一個任務,在默認情況下,同一個應用程序中的所有Activity都具有相同的affinity, 名字為應用的包名。當然了,我們可以為每個 Activity 都單獨指定 taskAffinity 屬性(不與包名相同)。taskAffinity 屬性主要和 singleTask 啟動模式和 allowTaskReparenting 屬性配對使用,在其他情況下沒有意義。
taskAffinity 有下面兩種應用場景:
分為顯示啟動和隱式啟動。
(1)顯示啟動
直接指定待調整的Activity類名。
(2)隱式啟動
Intent 能夠匹配目標組件的 IntentFilter 中所設置的過濾信息,如果不匹配將無法啟動目標 Activity。IntentFilter 的過濾信息有 action、category、data。
IntentFilter 需要注意的地方有以下:
● 一個 Activity 中可以有多個 intent-filter
● 一個 intent-filter 同時可以有多個 action、category、data
● 一個 Intent 只要能匹配任何一組 intent-filter 即可啟動對應 Activity
● 新建的 Activity 必須加上以下這句,代表能夠接收隱式調用
<category android:name="android.intent.category.DEFAULT" />
只要匹配一個action即可跳轉,注意的是action要區分大小寫。
規則:如果intent中有category,則所有的都能匹配到intent-filter中的category,intent中的category數量可用少於intent-filter中的。另外,單獨設置category是無法匹配activity的,因為category屬性是一個執行Action的附加信息。
intent不添加category會匹配默認的,即 「android:intent.category.DEFAULT」
如果上面例子,如果去掉intent.setAction("action_name"),則會拋出異常:
規則:類似action,但data有復雜的結構,只要匹配一個data並且與data中所有屬性都一致就能匹配到Activity,只要有1個屬性不匹配,都無法找到activity。
data的結構:
data 主要是由 URI 和 mimeType 組成的。
URI 可配置很多信息,的結構如下:
與url類似,例如:
mineType:指資源類型包括文本、圖片、音視頻等等,例如:text/plain、 image/jpeg、video/* 等
下面看下data匹配的例子:
只匹配scheme
只匹配scheme也是能匹配到activity的。
匹配scheme、host、port
將上面的data改為
匹配mineType
如果有mineType,則不能僅設置setData或setMineType了,因為setData會把mineType置為null,而setMineType會把data置為null,導致永遠無法匹配到activity,要使用setDataAndType。
使用scheme的默認值contentfile
注意該方法需要在startAtivity方法或者是finish方法調用之後立即執行,不能延遲,但可以在子線程執行。
而在windowAnimationStyle中存在四種動畫:
activityOpenEnterAnimation // 打開新的Activity並進入新的Activity展示的動畫
activityOpenExitAnimation // 打開新的Activity並銷毀之前的Activity展示的動畫
activityCloseEnterAnimation //關閉當前Activity進入上一個Activity展示的動畫
activityCloseExitAnimation // 關閉當前Activity時展示的動畫
overridePendingTransition的方式比較生硬,方法也比較老舊了,不適用於MD風格,google提供了新的轉場動畫ActivityOptions,並提供了兼容包ActivityOptionsCompat。
我們知道在onCreate和onResume裡面直接獲取到控制項寬高為0,那有什麼辦法獲取到控制項的實際寬高?只要有onWindowFocusChanged、view.post、ViewTreeObserver三種方式獲取。
當用戶點擊桌面圖標啟動APP時,背後的流程如下:
我們看到的手機桌面是Launch程序的界面,點擊應用圖標會觸發點擊事件,調用startActivity(intent),然後通過Binder IPC機制,與ActivityManagerService(AMS)通訊,AMS執行一系列操作,最終啟動目前應用,大概流程如下:
通過PackageManager的resolveIntent()收集跳轉intent對象的指向信息,然後通過grantUriPermissionLocked()方法來驗證用戶是否有足夠的許可權去調用該intent對象指向的Activity。如果有許可權,則在新的task中啟動目標activity,如果發現沒有進程,則先創建進程。
如果進程不存在,AMS會調用startProcessLocked創建新的進程,在該方法中,會通過socket的通訊方式通知zygote進程孵化新的進程並返回pid,在新的進程中會初始化ActivityThread,並依次調用Looper.prepareLoop()和Looper.loop()來開啟消息循環。
創建好進程後下一步要將Application和進程綁定起來,AMS會調用上一節創建的ActivityThread對象的bindAppliction方法完成綁定工作,該方法會發送一條BIND_APPLICATION的消息,最終會調用handleBindApplication方法處理消息,並調用makeApplication方法處理消息,載入APP的classes到內存中。
通過前面的步驟,系統已經擁有了該Application的進程,後續的啟動則是從已存在其他進程中啟動Acitivity,即調用realStartAcitvityLocked,該方法會調用Application的主線程對象ActivityThread的sheleLaunchActivity方法,在方法中會發送LAUNCH_ACTIVITY到消息隊列,最終通過handleLaunchActivity處理消息,完成Acitivty的啟動。
Activity
Activity 的 36 大難點,你會幾個?「建議收藏」
[譯]Android Application啟動流程分析