android顯示activity
① android 3.0以下的版本怎麼調出activity到前台
項目是環境是android,編譯版本是1.6,因為功能的需要,在手機使用界面activity1點擊返回鍵/Home鍵,不希望activity1退出,因此調用了moveTaskToBack,將任務移到了任務棧底,但當項目需要wifi下的安裝apk時,因考慮到許可權的問題,需要將activity1調出到前台,然後在其上調用安裝界面(需要用戶手動點擊安裝、取消),但又要activity截獲用戶的點擊結果(安裝or取消),所以使用startActivityForResult函數。
本想使用moveTastToFront將activity1顯示,但是貌似是3.0以上的版本才支持,只能放棄。
但試了多種調用activit1到前台,如下一:
[cpp] view plainprint?
Intent it1 = new Intent(context, activity1.class);
it1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
context.startActivity(it1);
Intent it1 = new Intent(context, activity1.class);
it1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
context.startActivity(it1);
但使用FLAG_ACTIVITY_NEW_TASK標記後,startActivityForResult的結果獲取不到,至少點擊返回/取消獲取不到(點擊安裝的話安裝成功會有廣播)
使用下面的方法(屏蔽FLAG_ACTIVITY_NEW_TASK標志),如下二:
[cpp] view plainprint?
Intent it1 = new Intent(context, activity1.class);
/ it1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
context.startActivity(it1);
Intent it1 = new Intent(context, activity1.class);
// it1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
context.startActivity(it1);
調出activity1到前台時又會碰到在4.2.2系統下不能顯示出來的問題,雖然在任務列表鍵上點擊運行的任務點擊activity1的apk時能在其上顯示安裝界面,但該界面需要用戶自己點擊出現,不符合要求。
最後google了幾次,發現「android的activity中不能使用startAcitivity來將自己提前到stack的前面,所以startActivity的context不能是自己的Activity。」(參考鏈接http://hi..com/cwhxguscbakrd/item/4358a413ad37f9f687ad4e91),根據提示,解決方法終於找到,即調用startActivity前調用下getApplicationContext(),如下:
[cpp] view plainprint?
Intent it1 = new Intent(context, activity1.class);
it1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); //兩種都可以
it1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.getApplicationContext().startActivity(it1);
Intent it1 = new Intent(context, activity1.class);
// it1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); //兩種都可以
it1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.getApplicationContext().startActivity(it1);
當然,因為要考慮到wifi下連續多次安裝apk的情況(在用戶點擊安裝、取消前又有新的apk安裝到來),同時要兼顧獲取安裝結果,所以如下改動:
[cpp] view plainprint?
public static void installPackage(Context context, File file, int requestCode) {
//安裝列表自己控制個進度,一次安裝有了結果後再進行下一個的安裝
activity1.m_bInInstallProcee = true;
//gxj: 如果需要,需要調出daemon到前台
if (!CommonTools.isAppOnForeground(context))
{
//貌似android 3.0以上才支持,若支持,直接使用即可
// context.moveTaskToFront();
Intent it1 = new Intent(context, activity1.class);
// it1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
it1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.getApplicationContext().startActivity(it1);
}
if (true)
{
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP );
intent.setAction(android.content.Intent.ACTION_VIEW);
Uri path = Uri.fromFile(file);
intent.setDataAndType(path, "application/vnd.android.package-archive");
if (requestCode < android.app.Activity.RESULT_CANCELED) {
context.startActivity(intent);
}
else {
((Activity) context).startActivityForResult(intent, requestCode);
}
}
}
public static void installPackage(Context context, File file, int requestCode) {
//安裝列表自己控制個進度,一次安裝有了結果後再進行下一個的安裝
activity1.m_bInInstallProcee = true;
//gxj: 如果需要,需要調出daemon到前台
if (!CommonTools.isAppOnForeground(context))
{
//貌似android 3.0以上才支持,若支持,直接使用即可
// context.moveTaskToFront();
Intent it1 = new Intent(context, activity1.class);
// it1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
it1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.getApplicationContext().startActivity(it1);
}
if (true)
{
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP );
intent.setAction(android.content.Intent.ACTION_VIEW);
Uri path = Uri.fromFile(file);
intent.setDataAndType(path, "application/vnd.android.package-archive");
if (requestCode < android.app.Activity.RESULT_CANCELED) {
context.startActivity(intent);
}
else {
((Activity) context).startActivityForResult(intent, requestCode);
}
}
}
其中判斷當前activity是否在前台的判斷如下:
[cpp] view plainprint?
public class CommonTools {
public static boolean isAppOnForeground(Context context) {
// Returns a list of application processes that are running on the
// device
ActivityManager activityManager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
String packageName = context.getApplicationContext().getPackageName();
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null)
return false;
for (RunningAppProcessInfo appProcess : appProcesses) {
// The name of the process that this object is associated with.
if (appProcess.processName.equals(packageName)
&& appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
return true;
}
}
return false;
}
}
② android 多個activity怎麼知道打開程序時首先是顯示哪個activity呢
在AndroidManifest.xml文件里可以配置
假如你創建了一個helloworld程序 那麼androidManifest.xml里會有這么一段
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".HelloworldActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
你把第2行的android:name=".HelloworldActivity"中的HelloworldActivity改為其他的activity名字就行了
③ android 小白問一下,一個應用已經打開,返回棧裡面已經有多個Activity,再次啟動如何顯示棧頂的Activity
再次啟動,默認就顯示棧頂的Activity.
有2種情況不是,一個是內存不足,會清除數據,啟動應用後從初始化main標識的頁面開始;另一個是應用自己退出了。
④ 如何在Android中實現懸浮Activity
這里主要有三個任務:
計算已有的Activity的尺寸並確定它的新坐標位置;
使Activity透明,可以看見其背景;
處理背景使其不能再和用戶進行交互。
計算窗口大小
前面提到,我們需要以一個已有的手機APP為基礎(使用了ActionBarSherlock庫),這個庫我們已經以一個外部庫的形式集成到項目中,並帶有源代碼。
如果對ABS的源碼很熟悉或者曾對原生ActionBar的構架有了解,就會發現:如果改變Activity的大小,那在調用
setContentView方法的時候,功能沒有實現:ActionBar的大小和位置都沒有變化。這時要做的就是在更高的級別里操作,在系統繪制
ActionBar的時候——ABS或者原生的ActionBar,這時候還沒有任何窗口的數據,這樣我們就可以按照需要調整了。
最顯而易見的方式就是改變Window的尺寸,所以這里需要以下這段代碼:
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
if (getResources().getBoolean(R.bool.is_tablet) && mOpenAsSmallWindow) {
final View view = getWindow().getDecorView();
final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) view.getLayoutParams();
lp.gravity = Gravity.CENTER;
lp.width = mActivityWindowWidth;
lp.height = mActivityWindowHeight;
getWindowManager().updateViewLayout(view, lp);
}
}
代碼執行完畢後,就可以看到窗口的大小已經根據mActivityWindowWidth和mActivityWindowHeight的值發生了改變。
is_tablet檢查只對平板有效,mOpenAsSmallWindow標識表示是否讓窗口全屏顯示或者是否作為新的窗口渲染。
如果在運行的時候報錯了,錯誤日誌是:ActionBarView can only be used with android:layout_width="match_parent" (or fill_parent).那不用擔心,我們有ABS的源碼,直接修改源碼就可以了。
打開ActionBarView這個文件,然後再onMeasure方法里把拋出的異常注釋掉——這樣應該就可以解決問題了。安卓上使用的是比較特殊的許可權控制機制,所以這里我們可以繼續深入的不多,也許還能粗略計算菜單項等,不過很多東西我們都不可把控。
注意:這個方法沒有在原生ActionBar上測試,因為這里只是在作者的Android版本中測試過。如果要禁用ActionBar,需要找到ActionBarSherlock這個類,然後注釋掉以下這行代碼:
// registerImplementation(ActionBarSherlockNative.class);
代碼運行應該沒問題,然後就可以看到不透明背景的Activity了。
添加透明功能
在實現了Activity的尺寸和大小都改變後,現在就要讓它透明了。可以給這個平板上的Activity主題添加這個屬性:
<item name="android:windowIsTranslucent">true</item>
這個屬性值可以使Activity背景透明。
看起來不錯,效果已經基本實現了。
還有一個小問題:以上測試的都是在Nexus7 android4.3上執行,而這個App在Nexus7 的android4.2版本中,Activity沒有顯示。
經過多次調試和日誌檢查後,發現我們的Activity(就叫MainActivity吧)沒有被銷毀(沒有調用onDestroy方法),所
以Android系統就把它忽略了,沒有繪制它。為什麼呢?因為Android 4.4
KitKat新增了一個優化演算法。因為這個優化演算法,Android系統看到Activity為全屏顯示模式(不管WindowManager的改變),
就會繪制這個MainActivity,但是它之上的東西就被忽略了,所以我們就看不到任何顯示了。
我們研究了下這個問題,然後發現對話框和其他不全屏顯示的部件都可以正常繪制,所以我們需要在主題theme里加上這幾行:
<item name="android:windowIsFloating">true</item>
<item name="android:windowCloseOnTouchOutside">false</item>
<item name="android:colorBackgroundCacheHint"><a href="http://www.jobbole.com/members/NULL/" rel="nofollow">@null</a></item>
<item name="android:backgroundDimEnabled">true</item>
⑤ android 如何獲取當前界面最上面的activity
在Android系統中,Activity窗口的大小是由WindowManagerService服務來計算的。WindowManagerService服務會根據屏幕及其裝飾區的大小來決定Activity窗口的大小。一個Activity窗口只有知道自己的大小之後,才能對它裡面的UI元素進行測量、布局以及繪制。本文將詳細分析WindowManagerService服務計算Activity窗口大小的過程。
一般來說,Activity窗口的大小等於整個屏幕的大小,但是它並不佔據著整塊屏幕。為了理解這一點,我們首先分析一下Activity窗口的區域是如何劃分的。
我們知道,Activity窗口的上方一般會有一個狀態欄,用來顯示3G信號、電量使用等圖標,如圖1所示。
圖1 Activity窗口的Content區域示意圖
從Activity窗口剔除掉狀態欄所佔用的區域之後,所得到的區域就稱為內容區域(Content Region)。顧名思義,內容區域就是用來顯示Activity窗口的內容的。我們再抽象一下,假設Activity窗口的四周都有一塊類似狀態欄的區域,那麼將這些區域剔除之後,得到中間的那一塊區域就稱為內容區域,而被剔除出來的區域所組成的區域就稱為內容邊襯區域(Content Insets)。Activity窗口的內容邊襯區域可以用一個四元組(content-left, content-top, content-right, content-bottom)來描述,其中,content-left、content-right、content-top、content-bottom分別用來描述內容區域與窗口區域的左右上下邊界距離。
我們還知道,Activity窗口有時候需要顯示輸入法窗口,如圖2所示。
圖2 Activity窗口的Visible區域示意圖
這時候Activity窗口的內容區域的大小有可能沒有發生變化,這取決於它的Soft Input Mode。我們假設Activity窗口的內容區域沒有發生變化,但是它在底部的一些區域被輸入法窗口遮擋了,即它在底部的一些內容是不可見的。從Activity窗口剔除掉狀態欄和輸入法窗口所佔用的區域之後,所得到的區域就稱為可見區域(Visible Region)。同樣,我們再抽象一下,假設Activity窗口的四周都有一塊類似狀態欄和輸入法窗口的區域,那麼將這些區域剔除之後,得到中間的那一塊區域就稱為可見區域,而被剔除出來的區域所組成的區域就稱為可見邊襯區域(Visible Insets)。Activity窗口的可見邊襯區域可以用一個四元組(visible-left, visible-top, visible-right, visible-bottom)來描述,其中,visible-left、visible-right、visible-top、visible-bottom分別用來描述可見區域與窗口區域的左右上下邊界距離。
在大多數情況下,Activity窗口的內容區域和可見區域的大小是一致的,而狀態欄和輸入法窗口所佔用的區域又稱為屏幕裝飾區。理解了這些概念之後,我們就可以推斷,WindowManagerService服務實際上就是需要根據屏幕以及可能出現的狀態欄和輸入法窗口的大小來計算出Activity窗口的整體大小及其內容區域邊襯和可見區域邊襯的大小。有了這三個數據之後,Activity窗口就可以對它裡面的UI元素進行測量、布局以及繪制等操作了。
從前面Android應用程序窗口(Activity)的繪圖表面(Surface)的創建過程分析一文可以知道,應用程序進程是從ViewRoot類的成員函數performTraversals開始,向WindowManagerService服務請求計算一個Activity窗口的大小的,因此,接下來我們就從ViewRoot類的成員函數performTraversals開始分析一個Activity窗口大小的計算過程,如圖3所示。
圖3 Activity窗口大小的計算過程
這個過程可以分為11個步驟,接下來我們就詳細分析每一個步驟。
Step 1. ViewRoot.performTraversals
這個函數定義在文件frameworks/base/core/java/android/view/ViewRoot.java中,它的實現很復雜,一共有600-行,不過大部分代碼都是用來計算Activity窗口的大小的,我們分段來閱讀:
[java] view plainpublic final class ViewRoot extends Handler implements
ViewParent,
View.AttachInfo.Callbacks {
......
private void performTraversals() {
......
final View host = mView;
......
int desiredWindowWidth;
int desiredWindowHeight;
int childWidthMeasureSpec;
int childHeightMeasureSpec;
......
Rect frame = mWinFrame;
if (mFirst) {
......
DisplayMetrics packageMetrics =
mView.getContext().getResources().getDisplayMetrics();
desiredWindowWidth = packageMetrics.widthPixels;
desiredWindowHeight = packageMetrics.heightPixels;
} else {
desiredWindowWidth = frame.width();
desiredWindowHeight = frame.height();
if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) {
......
windowResizesToFitContent = true;
}
}
復制代碼
這段代碼用來獲得Activity窗口的當前寬度desiredWindowWidth和當前高度desiredWindowHeight。
⑥ 在android開發中,先顯示Activity_1,由Activity_1跳轉到Activity_2
手勢只是動作,跳轉是行為,
先用手勢庫實現手勢動作,再把觸發操作放在手勢動作中即可
⑦ 如何獲得當前的activity android
android開發中獲取當前的Activity有多種情況;
在Activity中,this就是當前的Activity,例如this.startActivity。
在Fragment中可以通過 getActivity()來得到當前裝載這個Fragment的Activity。
通過Activity堆棧來獲取當前顯示的這個Activity
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
ComponentName cn = am.getRunningTasks(1).get(0).topActivity;
⑧ Android UI開發中,設置Activity的什麼屬性可以使Activity顯示為對話框樣式.
將activity設置成對話框樣式,只需在activity屬性裡面增加下面一句代碼: