androidapilevel獲取
A. Android 保持屏幕常亮的幾種方法
一、前言
在實際開發的過程中,會有一些需要保持屏幕常亮,避免進入鎖屏狀態的需求。最常見的就是視頻播放的過程中,如果屏幕突然暗了,或者直接鎖屏,會非常的影響用戶的體驗。
本篇文章就對 Android 下,如何保持屏幕常量,做一個簡單的記錄和總結。橘爛
二、幾種常見的方法
1、WakeLock
使用 WakeLock 是一種教科書式的比較常規的手段,使用起來也非常的簡單。
可以看到,WakeLock 主要是通過 PowerManager 獲取,然後通過acquire()方法獲取一個 WakeLock 資源,WakeLock 也是一種資源,在使用完成之後,別忘了調用release()方法進行釋放。
使用 WakeLock 還需要額外的聲明 WAKE_LOCK 許可權。
當然,使用 WakeLock 暫時來看,應該還是沒有什麼問題的。但是實際上,所有和屏幕亮度相關的 WakeLock 的 Flag ,在 API level 17+ 之上,都已經被標記廢棄了。可以看出 Android 在節能上做了很圓仿漏多努力,屏幕是大岩費電大戶,既然已經被廢棄掉了,正常來說,我們還是不推薦使用的。
更多和 PowerManager.WakeLock 相關的內容,可以看看之前的一篇文章《PowerManager 不是只有 WakeLock 》。
2、FLAG_KEEP_SCREEN_ON
前面說了,WakeLock 已經被標記廢棄。雖然被廢棄了,但是實際上 Android 還是給我們提供了對應的解決方案的,那就是使用FLAG_KEEP_SCREEN_ON的方式來標記屏幕常亮。
FLAG_KEEP_SCREEN_ON 使用起來也非常的簡單,它是一個頁面 Window 上的一個 Flag ,使用addFlags()方法添加。
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
當然,這里使用完成之後,也是需要取消掉的。取消這個 Flag 使用clearFlags()方法來取消。
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
通常我們會在一個 Activity 的onResume()和onPause()方法中,分別調用這兩個方法。
看看 FLAG_KEEP_SCREEN_ON 的文檔解釋。
從這里可以看出來,它只作用在一個被顯示的 Window 上,並且保持設備屏幕高亮度的常亮。
其實這里也可以看出來,官方廢棄 WakeLock 而推薦使用 FLAG_KEEP_SCREEN_ON ,一部分原因在於 WakeLock 是一個全局的資源,而 FLAG_KEEP_SCREEN_ON 只是一個和 window 相關的資源,作用范圍更小了一些。並且它比 WakeLock 更好的一點在於,它不需要額外的申請許可權,一般來說,我們還是推薦使用它的。
3、keepScreenOn
除了給 Window 添加一個 FLAG_KEEP_SCREEN_ON 的 Flag 之外,還可以對當前可見的 View 調用 keepScreenOn() 方法來設置屏幕常亮。
keepScreenOn() 是 View 對象上的方法,同時也提供了布局中的屬性android:keepScreenOn來方便我們在布局中對其進行設置。
需要注意的一點,使用 keepScreenOn() 設置的常亮標識,需要當前 View 保持屏幕可見才行。所以一般而言,我們會在頁面的根布局中,添加此屬性。
通過文檔可以看到,實際上它的原理和 FLAG_KEEP_SCREEN_ON 一樣的,只是它更簡單,只需要對某個 View 設置,如果該 View 可見即生效,否者就不生效。
4、MediaPlayer的 setScreenOnWhilePlaying()
如果我們是使用一個 MediaPlayer 來進行視頻播放的話,MediaPlayer 還提供了setScreenOnWhilePlaying()方法,來設置屏幕常量。
其實沒什麼好說的,繼續查看源碼可以看到其實最終調用的還是keepScreenOn()方法。當然多了解一種方法也沒有什麼壞處。
三、小結
保持屏幕常亮的方式有很多,選用我們需要的即可。當然,最好還是不要使用 WakeLock 了,比較已經被標記為廢棄了。
B. 如何調用Android系統程序詳細信息界面
調用Android系統「應用程序信息(Application Info)」界面「Android系統設置->應用程序->管理應用程序」列表下,列出了系統已安裝的應用程序。選擇其中一個程序,則進入「應用程序信息(Application Info)」界面。這個界面顯示了程序名稱、版本、存儲、許可權等信息,並有卸載、停止、清除緩存等按鈕,可謂功能不少。如果在編寫相關程序時(比如任務管理器)可以調用這個面板,自然提供了很大的方便。那麼如何實現呢?
在最新的Android SDK 2.3(API Level 9)中,提供了這樣的介面。在文檔路徑
docs/reference/android/provider/Settings.html#ACTION_APPLICATION_DETAILS_SETTINGS
下,有這樣的描述:
public static final String ACTION_APPLICATION_DETAILS_SETTINGS Since: API Level 9
Activity Action: Show screen of details about a particular application.
In some cases, a matching Activity may not exist, so ensure you safeguard against this.
Input: The Intent's data URI specifies the application package name to be shown, with the "package" scheme. That is "package:com.my.app".
Output: Nothing.
Constant Value: "android.settings.APPLICATION_DETAILS_SETTINGS"
就是說,我們只要以android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS作為Action;「package:應用程序的包名」作為URI,就可以用startActivity啟動應用程序信息界面了。代碼如下:
view plain
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts(SCHEME, packageName, null);
intent.setData(uri);
startActivity(intent);
但是,在Android 2.3之前的版本,並沒有公開相關的介面。
通過查看系統設置platform/packages/apps/Settings.git程序的源碼,可以發現應用程序信息界面為InstalledAppDetails。
在這里(2.1)還有這里(2.2),我們可以分別看到Android2.1和Android2.2的應用管理程序(ManageApplications.java)是如何啟動InstalledAppDetails的。
view plain
// utility method used to start sub activity
private void () {
// Create intent to start new activity
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClass(this, InstalledAppDetails.class);
intent.putExtra(APP_PKG_NAME, mCurrentPkgName);
// start new activity to display extended information
startActivityForResult(intent, INSTALLED_APP_DETAILS);
}
但是常量APP_PKG_NAME的定義並不相同。
2.2中定義為"pkg",2.1中定義為"com.android.settings.ApplicationPkgName"
那麼,對於2.1及以下版本,我們可以這樣調用InstalledAppDetails:
view plain
Intent i = new Intent(Intent.ACTION_VIEW);
i.setClassName("com.android.settings","com.android.settings.InstalledAppDetails");
i.putExtra("com.android.settings.ApplicationPkgName", packageName);
startActivity(i);
對於2.2,只需替換上面putExtra的第一個參數為"pkg"
綜上,通用的調用「應用程序信息」的代碼如下:
view plain
private static final String SCHEME = "package";
/**
* 調用系統InstalledAppDetails界面所需的Extra名稱(用於Android 2.1及之前版本)
*/
private static final String APP_PKG_NAME_21 = "com.android.settings.ApplicationPkgName";
/**
* 調用系統InstalledAppDetails界面所需的Extra名稱(用於Android 2.2)
*/
private static final String APP_PKG_NAME_22 = "pkg";
/**
* InstalledAppDetails所在包名
*/
private static final String APP_DETAILS_PACKAGE_NAME = "com.android.settings";
/**
* InstalledAppDetails類名
*/
private static final String APP_DETAILS_CLASS_NAME = "com.android.settings.InstalledAppDetails";
/**
* 調用系統InstalledAppDetails界面顯示已安裝應用程序的詳細信息。 對於Android 2.3(Api Level
* 9)以上,使用SDK提供的介面; 2.3以下,使用非公開的介面(查看InstalledAppDetails源碼)。
*
* @param context
*
* @param packageName
* 應用程序的包名
*/
public static void showInstalledAppDetails(Context context, String packageName) {
Intent intent = new Intent();
final int apiLevel = Build.VERSION.SDK_INT;
if (apiLevel >= 9) { // 2.3(ApiLevel 9)以上,使用SDK提供的介面
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts(SCHEME, packageName, null);
intent.setData(uri);
} else { // 2.3以下,使用非公開的介面(查看InstalledAppDetails源碼)
// 2.2和2.1中,InstalledAppDetails使用的APP_PKG_NAME不同。
final String appPkgName = (apiLevel == 8 ? APP_PKG_NAME_22
: APP_PKG_NAME_21);
intent.setAction(Intent.ACTION_VIEW);
intent.setClassName(APP_DETAILS_PACKAGE_NAME,
APP_DETAILS_CLASS_NAME);
intent.putExtra(appPkgName, packageName);
}
context.startActivity(intent);
}