原文:blog.fiftykg.com/html
經過本文,你能夠 一、瞭解一種特別的閃屏 二、瞭解android版本彩蛋的實現原理 三、得到一個android各版本彩蛋的demojava
在體驗App時發現了一款叫‘圖凌’的app,閃屏頁很是特別。從下圖能夠看到,是一個以桌面壁紙爲背景的頁面。 android
這種閃屏效果讓人眼前一亮,因此很是好奇他的實現原理。在不破解apk的狀況下(破解失敗,有騰訊樂固加固==),猜測了幾種實現方式:git
一、經過Api獲取壁紙,而後設置Activity的背景
二、特殊的Activity theme
複製代碼
在逐個驗證猜測以前,想到了一個頁面的實現與‘圖凌’的閃屏很是類似,就是Android的版本彩蛋(設置-關於手機-Android版本點擊3下)。而這個頁面是能夠找到源碼的。github
打開彩蛋頁面,執行如下命令,能夠得知Activity的名字是PlatLogoActivity。shell
adb shell dumpsys activity | grep "Focus"
mFocusedActivity: ActivityRecord{2829baa u0 android/com.android.internal.app.PlatLogoActivity t4844}
mFocusedStack=ActivityStack{d93bf0d stackId=1, 4 tasks} mLastFocusedStack=ActivityStack{d93bf0d stackId=1, 4 tasks}
複製代碼
(或者 adb shell dumpsys activity top
)api
經過在線源碼平臺Xref,找到PlatLogoActivity,源碼就不貼了,由於重點並不在PlatLogoActivity.java
,而是在AndroidManifest,theme纔是關鍵!也就是開始的第二個猜測。bash
<activity android:name="com.android.internal.app.PlatLogoActivity"
android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
android:configChanges="orientation|keyboardHidden"
android:process=":ui">
</activity>
複製代碼
經過源碼基本瞭解了實現原理,但沒有跑一下Demo是不靠譜的。 PlatLogoActivity的實現很是獨立,沒有太多依賴。因此copy了一下各個版本的PlatLogoActivity作了一個Demo。app
Github: github.com/PortgasAce/…ui
如今咱們已經知道theme能夠方便的實現‘圖凌’的閃屏效果。那麼代碼能夠實現嗎?官方有開放相應的api嗎?
這些問題的答案能夠從theme的實現原理入手。經過google或者xref搜索theme的一些關鍵字,最終能夠找到PhoneWindow#generateLayout有這樣一段解析theme標籤的代碼:
... //省略了不少標籤解析
if (a.getBoolean(R.styleable.Window_windowSwipeToDismiss, false)) {
requestFeature(FEATURE_SWIPE_TO_DISMISS);
}
if (a.getBoolean(R.styleable.Window_windowFullscreen, false)) {
setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));
}
...//省略了不少標籤解析
複製代碼
theme的主要實現就是經過window#requestFeature
和window#setFlags
方法改變樣式。
臨摹着寫了Theme.Wallpaper.NoTitleBar.Fullscreen
的java實現,見github:PlatLogoActivityNoStyle 主要代碼:
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().getDecorView().setWillNotDraw(true);
getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
複製代碼
到此爲止,猜測2經過theme和java實現都是驗證了。那麼其餘猜測是否可行呢? 答案固然是能夠的啦。經過sdk提供的WallpaperManager
能夠獲取桌面壁紙。
Drawable bg = WallpaperManager.getInstance(context).getDrawable();
rootView.setBackground(bg);
複製代碼
以上代碼就能夠給Activity設置背景爲桌面壁紙。
可是有一個問題。動態壁紙(live wallpapewr)時經過該方法獲取的drawable不但不會動,並且是錯誤的圖片。
其實liveWallpaper獲取的正確姿式是經過wallpaperManager#getWallpaperInfo#loadThumbnail
:
private Drawable getWallpaperDrawable() {
Drawable wallpaperDrawable;
PackageManager pm = getApplicationContext().getPackageManager();
WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
if (wallpaperManager.getWallpaperInfo() != null) {
/* * Wallpaper info is not equal to null, that is if the live wallpaper * is set, then get the drawable image from the package for the * live wallpaper */
wallpaperDrawable = wallpaperManager
.getWallpaperInfo().loadThumbnail(pm);
} else {
/* * Else, if static wallpapers are set, then directly get the * wallpaper image */
wallpaperDrawable = wallpaperManager.getDrawable();
}
return wallpaperDrawable;
}
複製代碼
可是問題仍是沒有徹底解決,背景不會動!每次調用loadThumbnail返回的圖片都是同樣的,所以猜測1只使用於靜態壁紙。
以上。
Andriod中Style/Theme原理以及Activity界面文件選取過程淺析:blog.csdn.net/qinjuning/a…